Umbraco Macros Appear to be Rendering Two or More Times - asp.net-mvc

Upon debugging my Umbraco solution (which was given to me by an outside consulting firm) and checking my error logs, I have noticed that it would appear that my macros are being hit in the code anywhere between 2 and 5 times. The macro isn't rendered that many times, it is just logging a warning and stepping through the code that many times.
Why is this? Is this basic Umbraco functionality or is there a mistake in my code?
My view under the Views -> MacroPartials folder looks like this:
#inherits Umbraco.Web.Macros.PartialViewMacroPage
#if (!string.IsNullOrEmpty(Model.MacroParameters["title"].ToString()))
{
<h2 class="#(Model.MacroParameters["hideBorder"].ToString() == "1" ? "" : "heading-border")">#Html.Raw(Model.MacroParameters["title"])</h2>
}
#if (!string.IsNullOrEmpty(Model.MacroParameters["subTitle"].ToString()))
{
<h2 class="large-body-copy">#Html.Raw(Model.MacroParameters["subTitle"])</h2>
}
Here is how I have the macro set up in the back office:

Related

Conditional statements using vue.js with html element

Im new to vue.js, and Im trying to do a simple if with a date field within my ASP.NET MVC project.
I've seen examples on vue tutorials where the condition is done in the js file, but Im not convinced that this would help me.
I currently have a date field in my ViewModel that has two drop downs. This is for an application form that asks a person how long have they lived at their address. They can select up to 11 months and 6+ years. I have a button that allows them to add another address. When you click this button, the viewModel for the date fields are repeated so they can add another one (stored in a List).
However I want to wrap this around a condition that says only if the date entered is less than 6 years then the button would appear. Like I said, at the min it is there always.
my code for the address and its button is:
<fieldset>
<legend>Please provide all your addresses in the last 6 years</legend>
#Html.EditorFor(m => m.PreviousAddresses)
</fieldset>
<button class="button">Add another previous address</button>
What im trying to do is something like v-if="PreviousAddress < 6" but I dont think thats right. Can someone help with the syntax?
EDIT: The validation works on the back end. Just need the client side to work with it:
[Minimum(72, ErrorMessage = "Please enter 6 years address history")]
public int TotalAddressHistoryInMonths
{
get
{
int totalMonths = CurrentAddress?.Duration?.TotalPeriodInMonths ?? 0;
if (PreviousAddresses != null)
{
foreach (ResidencyInputViewModel residency in PreviousAddresses)
{
totalMonths += residency?.Duration?.TotalPeriodInMonths ?? 0;
}
}
return totalMonths;
}
}
The solution you have appears to be correct, but can you post the rest of your code. Seeing the data object should help.

MVC Razor conditional code causing error?

I have the following code in a Razor view where I want to only display an address if the first piece is available.
#if (!string.IsNullOrWhiteSpace(Model.Address1))
{
#Model.Address1<br />
#Model.Address2<br />
#Model.City, #Model.State #Model.Zip
}
However, it's giving me a design time error saying "Can not use local variable 'Model' before it is declared".
I've done some searching on the syntax and as far as I can tell it looks correct but obviously I'm missing something. Can anyone see why this would work?
UPDATE
It's a little clunky looking but this is what I ended up with.
#if (!string.IsNullOrWhiteSpace(Model.Address1))
{
#:#Model.Address1<br />
if (!string.IsNullOrWhiteSpace(Model.Address2))
{
#:#Model.Address2<br />
}
#:#Model.City, #Model.State #Model.Zip
}
You're writing HTML which is being parsed as C# code, with confusing results.
The contents of a code block (such as #if) are parsed as code, not HTML.
Therefore, #Model.City, #Model.State #Model.Zip becomes a malformed variable declaration.
You need to wrap it in an HTML tag or <text>, or prefix each line with #:.

What should be the standard coding pattern for Sitecore

Using Sitecore 8.0, MVC, VS2015
I managed to generate the footer content as desired, for a practice site, but would like to know the standard way of doing things. The question is simple, but tried to explain in detail. Please bear with that :)
Requirement: The footer should display Office addresses and they should be editable by the Content author.
Sitecore Template : Location, Telephone 1, Telephone 2, IsActive(type-checkbox).
Datasource : A folder with items of the above template.
Code:
public class FooterViewModel
{
public List<Sitecore.Data.Items.Item> Addresses { get; set; }
}
public class FooterController : Controller
{
public ActionResult Footer()
{
var datasource = RenderingContext.Current.Rendering.Item;
FooterViewModel viewModel = new FooterViewModel();
viewModel.Addresses = new List<Item>();
if(datasource != null && datasource.HasChildren && datasource.Children.Count > 0)
{
foreach(Item address in datasource.Children)
{
if (address["IsActive"] == "1")
viewModel.Addresses.Add(address);
}
}
return View("~/Views/Shared/Footer.cshtml", viewModel);
}
}
Rendering the html using a Sitecore Controller Rendering
cshtml:
#using Sitecore.Mvc
#using Sitecore.Mvc.Presentation
#model Democore.Models.FooterViewModel
<div>
#foreach (var address in Model.Addresses)
{
<div>
<h3>#Html.Sitecore().Field("Location", address)</h3>
<ul>
<li>
#Html.Sitecore().Field("Telephone 1", address)
</li>
<li>
#Html.Sitecore().Field("Telephone 2", address)
</li>
</ul>
</div>
}
</div>
<div>
<p>&copy Copyright #DateTime.Now.Year. All rights reserved</p>
</div>
Here are my questions. (..well all 3 are more or less similar)
How to better this code/structure (or) in which case might it fail.
I did not like the way I hardcoded the field names in controller &
cshtml. What if the author changes the field names. How to tackle
that.
How does it work in a real scenario, say for eg if author
wants to show a third phone number. Will they contact the developer?
Because that requires a change in design & code too right?
This is a very broad question and will probably get closed -but here are some tips!
You controller is fine as far as error handling goes. You really want to add a global error handler for your site. This is a good example of that: http://www.sitecorenutsbolts.net/2015/10/23/Rendering-Exception-Handling-The-Right-Way/
You have 2 options - use constants and field ID's not the names, not a great option but works. A better option would be to use an ORM/Wrapper to do that. Two good ones are Fortis and Glass Mapper - both are very good - I contribute to Fortis so that would be my recomendation.
Normally if the design of the component changes it will require development support. You could use something like BrainJock's Score or ZenGarden to build your site and then the editor has a lot more control. But still likely would need a developer.
Hope this helps. For some info on good Sitecore architecture look here: Sitecore Helix and Sitecore Habitat

Umbraco PartialView Macros and #helper

This has been driving me crazy for about 3 hours now. We upgraded from Umbraco 4 to Umbraco 7 and now our site menus are broken. We used to use a script that traversed the nodes and created a CSS menu system.
So I have started reading up on the new stuff and I just can't even get a #helper or #functions block to work. The script is now using a PartialView Macro that uses a parameter called MenuNode that is the Node I want to traverse down.
Here's the code that works:
#inherits Umbraco.Web.Macros.PartialViewMacroPage
#{
var menuNode1 = string.IsNullOrEmpty((string)Model.MacroParameters["MenuNode"])? 0 : Convert.ToInt32(Model.MacroParameters["MenuNode"]);
}
<h1>#menuNode1</h1>
As soon as I try to add a #helper or #functions like in the Navigation PartialView example provided in Umbraco it stops working. Here is what breaks it.
#inherits Umbraco.Web.Macros.PartialViewMacroPage
#{
var menuNode1 = string.IsNullOrEmpty((string)Model.MacroParameters["MenuNode"])? 0 : Convert.ToInt32(Model.MacroParameters["MenuNode"]);
}
#TestHelper(menuNode1)
#helper TestHelper(var testvalue)
{
<h1>#testvalue</h1>
}
Can anyone point me at what I'm doing wrong?
Problem solved. It was because I was using var in the #helper parameter list, changed to dynamic and it worked fine.

NullReferenceException on an object not null

I'm passing an object to a view and am getting a null reference exception, but the object is not null.
In the Action I have this simple code:
return View(db.Users.First());
View code:
#model User
#using DG.WEB.Models
#{
ViewBag.SecondTitle = "Ver";
ViewBag.MostraEditarTab = "false";
ViewBag.MostraApagarTab = "false";
ViewBag.Tab = "tab2";
Layout = "~/Views/Conds/_Layout.cshtml";
}
<div class="container">
#if (Model != null)
{
<h5>#Model.Nome</h5>
<div id="container_atalhos">
<div class="btn-group">
<i class="icon-th-large"></i> Nova frac
<i class="icon-fire"></i> Nova OcorrĂȘncia
<i class="icon-shopping-cart"></i> Novo Fornecedor
<i class="icon-file"></i> Novo documento
<i class="icon-pencil"></i> Editar
<i class="icon-remove-circle icon-white"></i> Apagar
</div>
</div>
}else{
#:Not found
}
</div>
EDIT:
I just test a small code that prints the name of the first user in the view.
And it happens to me the same error!
The try / catch apparently works badly ... I do not understand.
Look at the picture
EDIT2:
I found the error. In the layout page there was an error and for some reason visual studio didnt detect it.
Thanks to all.
Usually such error are not directly related to the place where they blow up, but a consequence of IoC / Dependency Injection.
What basically happens is that in the background, the dependency injection is able to provide various objects as needed, but does this is a lazy fashion. So if something - like your layout page - isn't needed yet, it won't be created yet.
So then when you access something like your model, which can have internal requirements needing something like your layout, then the dependency injection kicks in, throwing an error at your model, even though the error is not model-related at all.
This is one of the really difficult aspects of dependency injection and will probably plague you again in the future :(.
There is also no best-practice I know of to avoid this. Your approach to gradually cornering the issue is the best way to go ahead AFAIK.

Resources