Currently this prevents the articles from opening. Tracing things back (remember i am a total noob at this)
I have tried a lot of different syntax and copied if statements that are used in a controller to get the same content
@if (model.freeProgram)
{
<div>free</div>
}
here is the model that contains the VMCards class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Web;
using Umbraco.Web;
using Umbraco.Web.PublishedContentModels;
namespace PerformanceSpace.Models
{
public class VM_RelatedCards
{
public string areaTitle { get; set; }
public bool pastOnly { get; set; }
public string pastURL { get; set; }
public string currentURL { get; set; }
public int displayLimit { get; set; }
public string card1Colour { get; set; }
public string cardTextColour { get; set; }
public string card2Colour { get; set; }
public string card3Colour { get; set; }
public bool altSizes { get; set; }
public bool doubleSizeFirst { get; set; }
public bool noCurrentPast { get; set; }
public bool showline { get; set; }
public List<VM_Cards> cards { get; set; }
public VM_RelatedCards()
{
init();
}
public VM_RelatedCards(IEnumerable<Artist> inputList)
{
init(inputList);
}
public VM_RelatedCards(IEnumerable<Program> inputList)
{
init(inputList);
}
public VM_RelatedCards(IEnumerable<Umbraco.Core.Models.IPublishedContent> inputList)
{
init(inputList);
}
private void init(IEnumerable<Umbraco.Core.Models.IPublishedContent> input = null, bool sizeAlternation = false)
{
pastOnly = true;
displayLimit = 3;
cards = new List<VM_Cards>();
altSizes = sizeAlternation;
doubleSizeFirst = false;
noCurrentPast = false;
showline = true;
if (input != null && input.Count() > 0) {
var T = input.First().GetType();
if (T == typeof(Artist)) {
foreach (Artist item in input) {
cards.Add(new VM_Cards(item)); } }
else if(T == typeof(Program)) {
foreach (Program item in input) {
cards.Add(new VM_Cards(item)); } }
else if(T== typeof(BlogPost)) {
foreach(BlogPost item in input) {
cards.Add(new VM_Cards(item)); } } }
}
private void init(IEnumerable<Artist> inputList)
{
init();
for (int count = 0; count < inputList.Count(); count++) {
var item = inputList.ElementAt(count);
cards.Add(new VM_Cards(item)); }
}
private void init(IEnumerable<Program> inputList)
{
init();
foreach (var item in inputList) {
cards.Add(new VM_Cards(item)); }
}
}
public class VM_Cards
{
public string colour { get; set; }
public string txtColour { get; set; }
public string title { get; set; }
public string subTitle { get; set; }
public string imgUrl { get; set; }
public string imgAlt { get; set; }
public string linkURL { get; set; }
public bool smallCard { get; set; }
public string cellClass { get; set; }
public bool doubleCrop { get; set; }
public bool freeProgram { get; set; }
public bool onlineProgram { get; set; }
public VM_Cards()
{
smallCard = false;
doubleCrop = false;
freeProgram = false;
}
public VM_Cards(Artist input, bool small = false, string textColour = null)
{
this.colour = input.HeadingColours.GetPropertyValue<string>("backgroundColour");
txtColour = textColour ?? gFuncs.textColourFromBG(colour);
title = input.FirstName + " " + input.LastName;
subTitle = input.HeadingText;
imgUrl = input.BiographyImage != null ? input.BiographyImage.Url : input.HeadingHeroImage.Url;
imgAlt = input.BiographyImage == null ? input.HeadingHeroImage.Name : input.BiographyImage.Name;
smallCard = small;
cellClass = "mb32";
linkURL = input.Url;
doubleCrop = false;
}
public VM_Cards(Program input, bool small = false, string textColour = null)
{
string format = (input.ProgramDates != null) ? ((List<Umbraco.Core.Models.IPublishedContent>)input.ProgramDates).ToMultiDate().MaxDate().Date <= DateTime.Now.AddMonths(-8) ? "MMM d, yyyy" : "MMM d" : null;
this.colour = input.HeadingColours.GetPropertyValue<string>("backgroundColour");
title = input.Title;
subTitle = input.ProgramDates != null ? input.ProgramDates.ToList().ToMultiDate().MinDate().ToString(format) + ((input.ProgramDates.Count() > 1) ? " - " + input.ProgramDates.ToList().ToMultiDate().MaxDate().ToString(format) : "") : "";
imgUrl = input.HeadingHeroImage.Url;
linkURL = input.Url;
smallCard = small;
txtColour = textColour ?? gFuncs.textColourFromBG(colour);
cellClass = "mb32";
doubleCrop = false;
freeProgram = "free";
}
public VM_Cards(program input, bool small = false)
{
string format = input.dateFinish.Year < DateTime.Now.Year ? "MMM d, yyyy" : "MMM d";
colour = input.bgColour;
txtColour = gFuncs.textColourFromBG(input.fgColour);
title = input.heading;
if (input.dateStart == new DateTime())
{
subTitle = "TBC";
}
else
{
subTitle = input.dateStart.ToString(format) + (input.dateStart.Date != input.dateFinish.Date ? " - " + input.dateFinish.ToString(format) : null);
}
imgUrl = input.img;
linkURL = input.url;
smallCard = small;
cellClass = "mb32";
doubleCrop = false;
freeProgram = "free";
}
public VM_Cards(BlogPost input, bool dblCrop = false)
{
//string format = "dddd MMMM dd yyyy";
title = input.Title;
//subTitle = input.CreateDate.ToString(format);
imgUrl = input.FeatureImage.Url;
imgAlt = input.FeatureImage.Name;
linkURL = input.Url;
colour = input.CardColour as string;
txtColour = gFuncs.textColourFromBG(colour);
doubleCrop = dblCrop;
}
}
}
So from my understanding this appears to be a model that is not created from making a doctype - there are no doctypes called VM
The freeProgam property alias is set originally in the Property model. Here is the property model header and related code.
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Umbraco.ModelsBuilder v3.0.10.102
//
// Changes to this file will be lost if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Web;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web;
using Umbraco.ModelsBuilder;
using Umbraco.ModelsBuilder.Umbraco;
namespace Umbraco.Web.PublishedContentModels
{
.
.
.
///<summary>
/// Free Program: Is this a free program?
///</summary>
[ImplementPropertyType("freeProgram")]
public bool FreeProgram
{
get { return this.GetPropertyValue<bool>("freeProgram"); }
}
I think I don't understand the relationship between the model created with modelsbuilder and how to use them in the other namespace (I'm not even really sure what a namespace is but I'm guessing it separates them somehow)
So what I would like to do is to add the word free in the items that have that property alias set. Where am I going wrong? Thanks so much in advance. I'm on a tight deadline as I was told this was a wordpress site and now they can't find anyone else to do it and the site goes live in two days... ergh....
**update (still need help)
more of an update. I can get the word free to hide or show on the program page. using this code
@{
if (!Model.GetPropertyValue
Not free
}
else
{
free
}
}
I'm just not sure how to reference it on the other namespace....
I'm not super sure what's going on here, some of your examples haven't displayed correctly but it does like you've stumbled across a complicated implementation.
Normally in an Umbraco View(Template) or PartialView the underlying 'Model' that the View is expecting to work with is of type RenderModel, which includes a property called Content that is of type IPublishedContent
So normally in an Umbraco View you can write out any property from the underlying content item, based on its Document Type definition using the alias of the property eg:
@using UmbracoTemplatePage
<h1>@Model.Content.GetPropertyValue<string>("title")</h1>
@if (Model.Content.GetPropertyValue<bool>("freeProgram")){
<h2>It's a Free program!!</h2>
}
else {
<h2>It's not a free program :-(</h2>
}
But people didn't like typing the ("freeProgram") bit in case they made a 'typo' and so Modelsbuilder was invented!
With Modelsbuilder turned on in the Web.config file, Umbraco will generate a C# Model for each DocumentType, and the above becomes something more like this:
@using UmbracoViewPage<MyDocTypeAlias>
<h1>@Model.Title</h1>
@if (Model.FreeProgram){
<h2>It's a Free program!!</h2>
}
else {
<h2>It's not a free program :-(</h2>
}
Which is 'less' to type, but whenever you change your Document Types you'll need to remember to 'regenerate your models' to update them to match (From the Developer section of Umbraco).
There are also several different modes for running Modelsbuilder in: PureLive where the models are generated in memory, and AppData where they are generated as files in the AppData folder (and need to be compiled and deployed to the site to work), and also DLL mode - where they are compiled into a DLL - the Models are generated under the default 'namespace' - Umbraco.Web.PublishedContentModels and a namespace is just a way of grouping models together and avoiding clashes with other models that might be generated in an application with the same name...
You've seen the generated Models, for your Document Type - and see that the property for 'FreeProgram' just uses the GetPropertyValue syntax and the alias 'freeProgram' to retrieve the value...
But you appear to have a further complication here... often the Model generated by Modelsbuilder which is 1-1 with the underlying DocumentType, doesn't cover 'ALL' the properties or things that might want to be written out in the PartialView, perhaps there is a list of latest News Articles to display, or some logic over whether to use the Image or a default Image if one is not picked - and here what developers might choose to do is to create a ViewModel - that is 1-1 with what is required for the View but not necessarily 1-1 with the Document Type... and I'm guessing that's what you have here, given the models are called VM_Cards... it's the ViewModel for writing out Cards.
Not there isn't an automatic way for Umbraco to know about these ViewModels, and they need to be wired up in Code - and usually this is done via an MVC Controller - Umbraco has this convention that if you create an MVC Controller that inherits RenderMvcController and name the controller DocumentTypeAliasController all requests for any content based on that Document Type will go through the Custom MVC Controller and it's usually here that someone might hijack the normal Umbraco request and create and populate a new ViewModel to use in a View.
Which makes it a bit convoluted if you 'just' want to add a new property!
So somewhere in your site, in a Controller or in a template view the ViewModel is created with a new keyword
eg
var relatedCards = new VM_RelatedCards(somethingHere);
and in particular there is a 'constructor' for VM_RelatedCards that takes a list of Programs to use as the source for creating the related cards:
public VM_RelatedCards(IEnumerable<Program> inputList)
{
init(inputList);
}
and I'm guessing that Program IS a model generated by Modelsbuilder based on the Program document type - so if your models have been regenerated since you added the FreeProgram checkbox, each of these Program objects will contain the FreeProgram true/false boolean value.
Now the constructor here calls init(inputList) method and passes through the list of Program objects to construct the ViewModel... funnily it knows at this stage what type of object it is... but doesn't let on to the init method which has to 'guess' which type of object it is, by looking at the first item in the list's type:
So you can see now for each Program, a new VMCards model is being created, and each Program item generated by Modelsbuilder is being passed in to the VMCards model constructor, which is implemented like so here:
Now your VM_Cards model does have a FreeProgram property of type 'bool
public bool freeProgram { get; set; }
but you can see in your constructor for VM_Cards that takes in a Program object, that the property freeProgram is being set to be a string value of "free"...
... so apologies for the long winded explanation but I think, this just needs to become...
I've solved it!!! all the code has been fine all along. Just spoke to the developer and I have to build the project (I had no idea) in Visual Studio by pressing ctrl + shift + b or none of the changes I have made (eg adding free program to the model)
Is that standard? I've never seen it mentioned in any umbraco docs. The dev said it was standard umbraco
Not so much 'standard' Umbraco but, 'standard' C#/.Net.
So yes, the Models generated by ModelsBuilder are created as files, and need to be compiled- but also those ViewModels, or anything that is C# code will also need to be compiled, to see any changes.
Rebuilding the Visual Studio solution will trigger that compiliation, but you can create code in a special app_code folder and have the compilation occur automatically.
Any changes in Views, eg Html or Razor code do not need to be compiled.
The benefits of compiling are that you should see any coding errors reported before you deploy your site, eg
freeProgram = "free";
Would have thrown an error during compilation because freeProgram is a boolean and not a string.
It's one of the reasons why people choose the ViewModel approach because more implementation logic is compiled, and so any typos etc are more likely to be found early. and you can write 'tests' against the code etc.
But it isn't the 'only way'
Anyway, I'm glad you got it working! - and you can mark your answer as the answer! :-P
Also I didn't mention this but I manually added the public bool freeProgram { get; set; } to the VM_Cards Model, is there somewhere else it should be added. I also have two models folders and both get used, one in the models folder in the root, which contains this VM cards and another in the AppData folder which seems to contain generated models.
I think there is something in the way this installation has been set up. I'm about to talk to the previous developer to see if they can point me in the right direction.
Trouble getting if statement to work
Hi!
I'm pretty new to this and working with a site in Umbraco v7 that already exists.
I am trying to display the word Free when the property alias freeProgram is true.
FreeProgram is already set up with a checkbox on doc type program
It is being used to create filters and it is referenced in a few places
This content is created from a partial template - here's the code (including on of many attempts to create content if freeProgram is true)
@{ var imgurl = String.Format("{0}?width={1}&height={2}&mode=crop", Model.imgUrl, Model.doubleCrop ? 700 : 400, Model.doubleCrop ? 400 : Model.smallCard ? 400 : 496); }
Currently this prevents the articles from opening. Tracing things back (remember i am a total noob at this)
I have tried a lot of different syntax and copied if statements that are used in a controller to get the same content
here is the model that contains the VMCards class
So from my understanding this appears to be a model that is not created from making a doctype - there are no doctypes called VM
The freeProgam property alias is set originally in the Property model. Here is the property model header and related code.
I think I don't understand the relationship between the model created with modelsbuilder and how to use them in the other namespace (I'm not even really sure what a namespace is but I'm guessing it separates them somehow)
So what I would like to do is to add the word free in the items that have that property alias set. Where am I going wrong? Thanks so much in advance. I'm on a tight deadline as I was told this was a wordpress site and now they can't find anyone else to do it and the site goes live in two days... ergh....
**update (still need help)
more of an update. I can get the word free to hide or show on the program page. using this code
@{ if (!Model.GetPropertyValue
Not free
} else {free
} }I'm just not sure how to reference it on the other namespace....
Hi Tara
I'm not super sure what's going on here, some of your examples haven't displayed correctly but it does like you've stumbled across a complicated implementation.
Normally in an Umbraco View(Template) or PartialView the underlying 'Model' that the View is expecting to work with is of type
RenderModel
, which includes a property calledContent
that is of typeIPublishedContent
So normally in an Umbraco View you can write out any property from the underlying content item, based on its Document Type definition using the alias of the property eg:
But people didn't like typing the ("freeProgram") bit in case they made a 'typo' and so Modelsbuilder was invented!
With Modelsbuilder turned on in the Web.config file, Umbraco will generate a C# Model for each DocumentType, and the above becomes something more like this:
Which is 'less' to type, but whenever you change your Document Types you'll need to remember to 'regenerate your models' to update them to match (From the Developer section of Umbraco).
There are also several different modes for running Modelsbuilder in: PureLive where the models are generated in memory, and AppData where they are generated as files in the AppData folder (and need to be compiled and deployed to the site to work), and also DLL mode - where they are compiled into a DLL - the Models are generated under the default 'namespace' -
Umbraco.Web.PublishedContentModels
and a namespace is just a way of grouping models together and avoiding clashes with other models that might be generated in an application with the same name...You've seen the generated Models, for your Document Type - and see that the property for 'FreeProgram' just uses the GetPropertyValue syntax and the alias 'freeProgram' to retrieve the value...
But you appear to have a further complication here... often the Model generated by Modelsbuilder which is 1-1 with the underlying DocumentType, doesn't cover 'ALL' the properties or things that might want to be written out in the PartialView, perhaps there is a list of latest News Articles to display, or some logic over whether to use the Image or a default Image if one is not picked - and here what developers might choose to do is to create a ViewModel - that is 1-1 with what is required for the View but not necessarily 1-1 with the Document Type... and I'm guessing that's what you have here, given the models are called VM_Cards... it's the
ViewModel
for writing out Cards.Not there isn't an automatic way for Umbraco to know about these ViewModels, and they need to be wired up in Code - and usually this is done via an
MVC Controller
- Umbraco has this convention that if you create an MVC Controller that inheritsRenderMvcController
and name the controllerDocumentTypeAliasController
all requests for any content based on that Document Type will go through the Custom MVC Controller and it's usually here that someone might hijack the normal Umbraco request and create and populate a newViewModel
to use in a View.Which makes it a bit convoluted if you 'just' want to add a new property!
So somewhere in your site, in a Controller or in a template view the ViewModel is created with a new keyword
eg
and in particular there is a 'constructor' for VM_RelatedCards that takes a list of
Program
s to use as the source for creating the related cards:and I'm guessing that
Program
IS a model generated by Modelsbuilder based on the Program document type - so if your models have been regenerated since you added the FreeProgram checkbox, each of these Program objects will contain the FreeProgram true/false boolean value.Now the constructor here calls init(inputList) method and passes through the list of Program objects to construct the ViewModel... funnily it knows at this stage what type of object it is... but doesn't let on to the init method which has to 'guess' which type of object it is, by looking at the first item in the list's type:
So you can see now for each Program, a new VMCards model is being created, and each Program item generated by Modelsbuilder is being passed in to the VMCards model constructor, which is implemented like so here:
Now your VM_Cards model does have a FreeProgram property of type 'bool
but you can see in your constructor for VM_Cards that takes in a
Program
object, that the property freeProgram is being set to be a string value of "free"...... so apologies for the long winded explanation but I think, this just needs to become...
But possible this is the very first thing you tried and it didn't work because the Modelsbuilder models weren't regenerated and so this gave an error?
With this set wherever the VM_Cards object is used you should be able to check the value using
Anyway hope this helps demystify your model shenanigans, (and also Umbraco doesn't need to be this complicated!!!)
regards
Marc
I've solved it!!! all the code has been fine all along. Just spoke to the developer and I have to build the project (I had no idea) in Visual Studio by pressing ctrl + shift + b or none of the changes I have made (eg adding free program to the model)
Is that standard? I've never seen it mentioned in any umbraco docs. The dev said it was standard umbraco
Hi Tara
Not so much 'standard' Umbraco but, 'standard' C#/.Net.
So yes, the Models generated by ModelsBuilder are created as files, and need to be compiled- but also those ViewModels, or anything that is C# code will also need to be compiled, to see any changes.
Rebuilding the Visual Studio solution will trigger that compiliation, but you can create code in a special app_code folder and have the compilation occur automatically.
Any changes in Views, eg Html or Razor code do not need to be compiled.
The benefits of compiling are that you should see any coding errors reported before you deploy your site, eg
Would have thrown an error during compilation because freeProgram is a boolean and not a string.
It's one of the reasons why people choose the ViewModel approach because more implementation logic is compiled, and so any typos etc are more likely to be found early. and you can write 'tests' against the code etc.
But it isn't the 'only way'
Anyway, I'm glad you got it working! - and you can mark your answer as the answer! :-P
regards
Marc
Thanks you so incredibly much for this detailed explanation!!! it's so helpful and I am understanding a lot more from it.
I had not tried
so I will try that - I had put the "free" in there just copying the way the other booleans were done
I'll give that a go now and see if I can get any info
Thanks!
Hi,
I tried your suggestions and again it just returns no results as soon as I add
to the render card page.
Also I didn't mention this but I manually added the
public bool freeProgram { get; set; }
to the VM_Cards Model, is there somewhere else it should be added. I also have two models folders and both get used, one in the models folder in the root, which contains this VM cards and another in the AppData folder which seems to contain generated models.I think there is something in the way this installation has been set up. I'm about to talk to the previous developer to see if they can point me in the right direction.
is working on a reply...
This forum is in read-only mode while we transition to the new forum.
You can continue this topic on the new forum by tapping the "Continue discussion" link below.