Partial view not rendering because TempData is null - asp.net-mvc

Here is part of my Index view:
#if (TempData["SucessAlert"] != null)
{
Html.RenderPartial("~/Views/Shared/_SuccessAlert.cshtml");
}
Here is the partial view, _SuccessAlert.cshtml:
<div class="alert alert-success alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
#TempData["SuccessAlert"]
#TempData["SuccessAlertLinkText"]
</div>
Here is part of my controller:
TempData["SuccessAlert"] = "Successfully created account code " + mergedCode + ".";
TempData["SuccessAlertLinkText"] = "Click here to view it.";
TempData["SuccessAlertLink"] = "/AccountCode/Details?Division=" + viewModel.Division
+ "&ProgramCode=" + viewModel.ProgramCode
+ "&ProjectCode=" + viewModel.ProjectCode
+ "&includeDisabled=False&page=1";
return RedirectToAction("Index");
Everything worked fine until I added the #if() statement to the view. Apparently TempData["SuccessAlert"] is always null when this #if statement is checked. Actually, if I change the #if() statement to #if(true), it still works, so TempData has the correct values inside the partial view, even though it's null in view itself.
Any idea what I'm doing wrong? (I'm using MVC5, if that matters.)

Bah! I just realized I misspelled "Success" as "Sucess" (one "C") in the #if() statement. I'm going to leave this here to document the fact that I am an idiot, as well as on the off chance that someone else will find this lesson useful -- double-check the spelling of TempData and ViewBag keys.

Related

ASP.NET MVC: why is this code within my view displaying "<br>" rather than a line break?

I have some code in my view which displays an employee's info (name, address, etc), within a grid. I'm having a problem however, when an employee's "Address 2" has data. In this circumstance, I need to place the Address 2 on a new line, within the same grid cell as Address 1.
So it should display as follows:
Name
Address
John Smith
123 My St
Amy Andrews
456 Main StApt B.
Instead however, my Address 2 is displaying the following, which physically displays the "br" tag:
456 Main St<br>Apt B.
Here's my code, which basically says, display "AddressLine1" and IF "AddressLine2" is not null, then include a line break, followed by AddressLine2.
I know I can get this to work by breaking out the AddressLine1 & AddressLine2 segments & I'm not against it, but I'd prefer to keep it similar to the code that already exists, which is written similar to the following, if possible:
#if (member.Employee != null)
{
<td>
#(member.Employee.FullName != null ? member.Employee.FullName : "-" )
</td>
<td>
#(member.Employee.AddressLine1 != null ? member.Employee.AddressLine1 +
(member.Employee.AddressLine2 != null ? "<br/>" +
member.Employee.AddressLine2 : "")
: "-" )
</td>
...
}
Thanks for any help.
The code doesn't emit the tag <br/> but a string that contains "<br/>". Use an #if block to emit the data you want instead, the same way you did for member.Employee :
<td>
</td>
#(member.Employee.FullName ?? "-" )
<td>
#(member.Employee.AddressLine1 ?? "-")
#if(member.Employee.AddressLine2 != null)
{
<br/>
#(member.Employee.AddressLine2)
}
</td>

Dynamic data from ViewBag on Partial View rendered on _Layout

Here I have a partial view in MVC 5
#modelType HOA5.MainMenuModel
<div class="navbar navbar-inverse navbar-fixed-top" id="mainNavbar">
<div class="container">
#Html.Raw(ViewBag.htmlstr)
</div>
</div>
...and the controller returns some dynamic content to ViewBag
Function Index() As ActionResult
Dim vModal As New MainMenuModel
vModal.MenuHTML = SB.ToString
Dim MenuHTML As String = ReturnMenu()
ViewBag.htmlstr = MenuHTML
Return View("MainMenuView")
End Function
... and then run just that view
http://localhost:52735/mainMenu/
It works perfectly and inserts the dynamic content. However, when I add the partial view to _Layout
#Html.Partial("~/Views/MainMenu/MainMenuView.vbhtml")
and run it
http://localhost:52735
Then the static content appears, but not the dynamic content.. Have also tried variants of #RenderAction, #RenderPartial but either that is not correct, or I have messed up the syntax!
Any pointers would be appreciated as head has been introduced to wall too many times today :-)
Thank you
As is so often we make things more complicated :-)
The easy fix was to make the function that returns the HTML string an ActionResult
Function ReturnMainMenu() As ActionResult
Try
strSQL = "SELECT * FROM Customers"
Using DS As DataSet = ReturnDataSet_Data(strSQL, 2, False)
For Each row As DataRow In DS.Tables(0).Rows
Next
End Using
Dim vModal As New MainMenuModel
Dim SB As New StringBuilder
SB.Append("<div class=""navbar navbar-inverse navbar-fixed-top"" id=""mainNavbar"">")
SB.Append("<div class=""container"">")
SB.Append("<div class=""navbar-header"">")
SB.Append("<button type=""button"" class=""navbar-toggle"" data-toggle=""collapse"" data-target="".navbar-collapse"">")
SB.Append("<span class=""icon-bar""></span>")
SB.Append("<span class=""icon-bar""></span>")
SB.Append("<span class=""icon-bar""></span>")
SB.Append("</button>")
SB.Append("<a class=""navbar-brand"" href=""/"">Add Variable Here xxx</a>") ' Add the variable here
SB.Append("</div>") ' End of navbar-header
SB.Append("<div class=""navbar-collapse collapse"">")
SB.Append("<ul class=""nav navbar-nav"">")
SB.Append("<li>Home</li></li>")
SB.Append(" <li>Upload eInvoice</li>")
SB.Append("<li>Contact</li>")
SB.Append("</ul>")
SB.Append("</div>") 'end of navbar-collapse
SB.Append("</div>")
SB.Append("</div>")
Dim checkstring As String = SB.ToString
vModal.MenuHTML = SB.ToString
Return Content(checkstring)
Catch ex As Exception
Return Nothing
End Try
End Function
Then (now I understand the syntax) add it to _Layout
#Html.Action("ReturnMainMenu", "MainMenu")
...and everything works....

MVC Parameterized Element

I have a partial view which I want to display a different type of HTML element based on a property of the model. The solution I've come up with is:
#if (Model.Element == "span")
{
<span>
Some stuff
</span>
}
else if (Model.Element == "p")
{
<p>
Some stuff
</p>
}
else
{
<div>
SomeStuff
</div>
}
This is obviously not very extensible. I'd like to write something like:
<#Model.Element>
Some stuff
</#Model.Element>
but it doesn't seem to be allowed. Is there any way to do something like this.
(I appreciate that this goes somewhat against the grain of MVC as the model and therefore the controller is specifying HTML. Actually, the element type comes from the parent view, so I think this is okay.)
Many thanks in advance.
#Html.Raw("<" + Model.Element + ">")
Some Stuff
#Html.Raw("</" + Model.Element + ">")
Is about as simple as possible. Though you could always use the TagBuilder:
#{
TagBuilder tb = new TagBuilder(Model.Element);
tb.InnerHtml = "Some Stuff";
#Html.Raw(tb.ToString())
}

Unexpected NullReferenceException in View

I have a Razor view that starts like:
#using My.Models
#model MySpecificModel
#{
ViewBag.Title = "My Title";
// NullReferenceException here:
string dateUtc =
(Model == null ? DateTime.UtcNow.ToShortDateString() :
Model.Date.ToShortDateString());
I see no reason for the NullReferenceException in the last line (note: the " = ? :" stuff is on one line in my source code. It is formatted to fit here.)
I then remove the declaration of/assignment to dateUtc and the NullReferenceException moves up to the ViewBag.Title line:
#using My.Models
#model MySpecificModel
#{
ViewBag.Title = "My Title"; // NullReferenceException here:
How can this possibly happen? ViewBag is of course not null.
NOTE 1: This only happens if Model is null.
NOTE 2: MySpecificModel.Date is of type DateTime, so can never be null.
A NullReferenceException on ViewBag.Title can indicate the error is really on a nearby line. In this example the error was thrown on line 1 but the real error was the null Model.Invoice in line 3.
<h2>#ViewBag.Title</h2>
<div class="pull-right">
<button onclick="addInvoice('#Model.Invoice.InvoiceId');">Add Invoice</button>
</div>
Also ASP.NET MVC Razor does not handle nulls in ternary statements like C# does.
//Ternaries can error in Razor if Model is null
string date = (Model == null ? DateTime.Now : Model.Date);
//Change to
string date = null;
if (Model == null)
date = DateTime.Now;
else
date = Model.Date;
You provide an empty default model which does nothing. It will be just so the Model isn't null. It will help to have an IsEmpty property . Better yet, if it can be applied in your case, a model with default values. The important thing is the Model not being null ever
You will get a null exception if you do not pass any model to the view and still have the view bound to a model e.g.:
#model MySpecificModel
When you did not pass such a model to the view from your controller.

Conditional inside foreach inside conditional with Razor

I'm trying to learn Razor but have come up against a syntax problem. When I run the following code:
#if (searchTerm != ""){
<h2>Showing #ExamineManager.Instance.Search(searchTerm, true).Count() results for #searchTerm</h2>
<div class="search-results">
#foreach (var result in ExamineManager.Instance.Search(searchTerm, true)) {
if (result.Fields["nodeTypeAlias"] == 'File'){
<p>File</p>
}else{
<p>Not file</p>
}
}
</div>
}
this errors, saying "Too many characters in character literal". The actual mechanism of the code works, it's just a syntax problem with the way the conditionals are nested I think, but I've tried various combinations of #{} blocks and prepending # to various lines but just can't get it to work.
Can anyone see what I'm doing wrong?
Thanks!
'File' is invalid syntax. You probably meant "File" in your if condition when you want to work with strings:
if (result.Fields["nodeTypeAlias"] == "File")
That is because you've got comparison
result.Fields["nodeTypeAlias"] == 'File'
In c#, you cannot write strings into single quotes like that. You should change it into
result.Fields["nodeTypeAlias"] == "File"
Just change the Code In this way
#{
if (searchTerm != ""){
<h2>Showing #ExamineManager.Instance.Search(searchTerm, true).Count() results for #searchTerm</h2>
<div class="search-results">
foreach (var result in ExamineManager.Instance.Search(searchTerm, true)) {
if (result.Fields["nodeTypeAlias"] == 'File'){
<p>File</p>
}
else{
<p>Not file</p>
}
}
</div>
}
}
THis code will help you

Resources