Why would this partial view return a blank? - asp.net-mvc-3

I have a partial view that I am creating to apply a special format to some decimal numbers. Here is the partial view ("_Dollar"):
#model decimal?
#if (Model.HasValue)
{ Html.Display(Model.Value.ToString("$#,0.00;$#,0.00-;0.00")); }
else { Html.Display("0.00"); }
Here is the calling line of code:
<td style="text-align:right;">#Html.DisplayFor(modelItem => item.TotalBill, "_Dollar")</td>
Any ideas of what might be going on?
Update: I should add, when running debug, the partial view is called and runs as I would expect it to. To me, is seems the problem is with how I am using Html.Display.
Update: I understand based on #Gaby's answer why my previous trial doesn't work. I made the changes, but it still doesn't work. On my view I have #Html.Partial("_Dollar",item.TotalBill) in the partial view I now have:
#model decimal?
#if (Model.HasValue)
{ Html.Raw(Model.Value.ToString("$#,0.00;$#,0.00-;0.00")); }
else { Html.Raw("0.00"); }

Html.Display does not do what you think it does.. read http://msdn.microsoft.com/en-us/library/ee310180%28v=VS.98%29.aspx
You should use
#model decimal?
#if (Model.HasValue)
{ #Html.Raw(Model.Value.ToString("$#,0.00;$#,0.00-;0.00")); }
else { #Html.Raw("0.00"); }

Related

Render different partial views

I'm trying to render different partial views from the _Layout file depending on what function I'm in, controller-wise.
The partial view is in the right column of the website which is located in the _Layout like so:
<aside id="right">
#Html.Partial("RightPartial")
</aside>
What I want to do is render a different partial view depending on where I am.
If I'm in the Index view I might want to view news and in the About view I might want to view phone numbers or something.
Appreciate any help :)
#{
string currentAction = ViewContext.RouteData.GetRequiredString("action");
string currentController = ViewContext.RouteData.GetRequiredString("controller");
}
Now based on the values of those variables decide which partial to render. To avoid polluting the Layout I would write a custom HTML helper:
<aside id="right">
#Html.RightPartial()
</aside>
which might look like this:
public static class HtmlExtensions
{
public static IHtmlString RightPartial(this HtmlHelper html)
{
var routeData = html.ViewContext.RouteData;
string currentAction = routeData.GetRequiredString("action");
if (currentAction == "Index")
{
return html.Partial("IndexPartialView");
}
else if (currentAction == "About")
{
return html.Partial("AboutPartialView");
}
return html.Partial("SomeDefaultPartialView");
}
}

Why doesn't my partial view work?

This is bugging me and I don't know what is going on. I created a partial view to format a number properly.
The file _PermitNumber.cshtml is in /Views/Shared and contains:
#model System.Int32
#Html.Raw(Model.ToString("00-0000"))
On my main page I do:
#Html.DisplayFor(model => model.BuildingPermit.PermitId, "_PermitNumber")
model.BuildingPermit.PermitId is defined as an int.
My output is 120456 instead of the expected 12-0456.
What is going on?
Why are you using a view for formatting your output? That seems like an unnecessary piece of complexity you are adding to your view. IMO a better location for this would be within a property of your view model:
public string FormattedPermitNumber
{
get
{
return PermitId.ToString("00-0000"));
}
}
But to answer your question, if you were delete your partial view, you will see that your number is still displaying as 120456. In order to render your partial view you need to render the partial as follows:
#{ Html.RenderPartial("_PermitNumber", Model.BuildingPermit.PermitId); }

MVC3 Razor and simulating same-page sections

Razor doesn't support same-page sections, so I can't do something like this:
#if (wrapSection)
{
<div class="section-wrapped-in-div">
#RenderSection("mySection")
</div>
}
else
{
#RenderSection("mySection")
}
#section mySection
{
some stuff here...
}
I know I can accomplish this with a partial view, but this is specific to this page, and really would be best kept on the same page.
Is something like this possible?
You should make a helper method:
#helper MySection(...) {
...
}
#MySection(...)
Unlike sections, helpers can also take parameters.

Razor behaving strangely?

Razor is playing tricks with me. I have a partial view:
#model ManageMvc.Models.Default.Classes.MvcModule
#{
if (Model.CanExpand)
{
Response.Write("Crazy");
#:TEST
<text>ojiiojjiojiojiojiojiojiojio</text>
Response.Write("Crazy2");
}
else
{
Response.Write("Crazy");
#:TEST
<text>ssssssssdffffffff</text>
Response.Write("Crazy2");
}
}
This is called from this:
#if (Model.Modules.Count > 0)
{
for (var i = 0; i < Model.Modules.Count; i++)
{
Html.Partial("~/Views/UserControls/_MenuItem.cshtml", Model.Modules[i]);
}
....
}
I expected razor to print out whats written inside the Text block and the #: block. But i get nothing. When i run this it just prints CrazyCrazy2 (for each module in the list).
Did i miss something?
Updated
The code that is calling if (Model.Modules.Count > 0) is a partial itself. That one is called from the layout page. So the top code is the second partial being called. Can this make any difference?
Layout -> MainMenu (partial) -> CreateMenuItem (partial)
Updated
This is the new code: (_MenuItem.cshtml inside Shared->DisplayTemplates)
#model ManageMvc.Models.Default.Classes.MvcModule
#{
if (Model.CanExpand)
{
#:TEST
<text>ojiiojjiojiojiojiojiojiojio</text>
}
else
{
#:TEST
<text>ssssssssdffffffff</text>
}
}
Partial view MainMenu that is calling the menu item:
#Html.DisplayFor(x => x.Modules, "_MenuItem")
Now this breaks on that line and i get the following error:
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[ManageMvc.Models.Default.Classes.MvcModule]', but this dictionary requires a model item of type 'ManageMvc.Models.Default.Classes.MvcModule'.
Put an # when calling the Html.Partial helper and avoid using Response.Write in an ASP.NET MVC view:
for (var i = 0; i < Model.Modules.Count; i++)
{
#Html.Partial("~/Views/UserControls/_MenuItem.cshtml", Model.Modules[i]);
}
Also instead of writing some ugly loops I would strongly suggest you using templated helpers. So replace the for loop in your layout with this simple helper:
#Html.DisplayFor(x => x.Modules)
and then define the display template (~/Views/Shared/DisplayTemplates/MvcModule.cshtml) which will be rendered for each element of the Modules collection:
#model ManageMvc.Models.Default.Classes.MvcModule
#if (Model.CanExpand)
{
#:TEST
<text>ojiiojjiojiojiojiojiojiojio</text>
}
else
{
#:TEST
<text>ssssssssdffffffff</text>
}
See how easier this is?

MVC 3 Razor view BeginForm is not posting to controller in FF, but works in IE 9

I have a form in MVC 3 razor view that I am trying to post to my controller.
I need these:
1) Post the form to the controller action.
2) The action should do something with the data &return a string status (OK if success or NOK if failed)
3) Based on the result I might redirect the user after a brief delay.
4) I also want to prevent duplicate submission (if possible)
This is how my view looks (I trimmed it):
#model <MyNameSpace.Model>
#{
ViewBag.Title = "Save";
Layout = "~/Views/Shared/MyMaster.cshtml";
}
#using (Html.BeginForm("save", "my_controller"))
{
<div>
#Html.TextBoxFor(m => m.Host, new { #style = "width: 520px" })
... set other fields on the form ...
<input type="submit" id="btnSubmit" value="Submit"/>
</div>
}
This is my controller:
public String Save(<ModelName> model)
{
return "OK";
}
This seems working in IE9. But nothing happens in FF 4 or Opera. HttpFox shows no activity.
What is missing?
Thanks
In ASP.NET MVC it is considered good practice to have your controller actions return ActionResults instead of strings. This way proper content type headers will be set, etc...
So for example:
[HttpPost]
public ActionResult Save(ModelName model)
{
return Content("OK", "text/plain");
}
or if you wanted to return some view:
[HttpPost]
public ActionResult Save(ModelName model)
{
return View("Success");
}
Your example looks kosher, so either something critical is missing from your example code, or you need to view the generated HTML to see what's missing.
Did you omit the code that actually displayed the view to the user? I'm unsure of how this would function without a bit more. I mocked up your code and put in what I considered correct.
[HttpGet]
public ViewResult Save()
{
var vm = new ModelTest();
return View(vm);
}
[HttpPost]
public ActionResult Save(ModelTest model)
{
//do stuff with model
//Set a value in TempData -- Meets requirement of storing a status
TempData["Message"] = "OK";
//RedirectToRoute -- Meets requirement of preventing multiple posts partially. Some javascript will also help with this
RedirectToRoute("routename");
}
Post happened as expected in FF 4.01/5.0
Your model looks ok, it's just the controller code appears lacking.
Hopefully this helps.

Resources