MVC3 Razor and simulating same-page sections - asp.net-mvc-3

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.

Related

ASP.NET MVC3 HtmlHelper extension method like BeginForm that uses a partial view?

I created an extension method based on this answer to the SO question c# - How can I create a Html Helper like Html.BeginForm - Stack Overflow and it works fine.
Can I move the embedded HTML in the extension method into a partial view and use that partial view in the method while preserving it's current behavior? In particular, I want to be able to 'wrap' a block of arbitrary HTML.
I ask not out of any pressing need, but simply out of a desire to maintain HTML consistently, e.g. as views and partial views. I imagine it will be a lot easier to spot any problems with the HTML if it's in a view or partial view too.
Here's the HtmlHelper extension method:
public static IDisposable HelpTextMessage(this HtmlHelper helper, bool isHidden, string heading)
{
TextWriter writer = helper.ViewContext.Writer;
writer.WriteLine(
String.Format(
"<div class=\"help-text {0}\">",
isHidden ? "help-text-hidden" : ""));
writer.WriteLine(
String.Format(
"<div class=\"help-text-heading\">{0}</div>",
heading));
writer.Write("<div class=\"help-text-body\">");
return new HelpTextMessageContainer(writer);
}
Here's the HelpTextMessageContainer class:
private class HelpTextMessageContainer : IDisposable
{
private readonly TextWriter _writer;
public HelpTextMessageContainer(TextWriter writer)
{
_writer = writer;
}
public void Dispose()
{
_writer.Write("</div></div>");
}
}
In a view, I can use the extension method like this:
#using(Html.HelpTextMessage(Model.HelpText.IsHelpTextHidden(Model.SomeHelpMessage), "Something"))
{
#:To do something, first do something-more-specific, then do another-something-more-specific.
}
Or I could use it like this too:
#using(Html.HelpTextMessage(Model.HelpText.IsHelpTextHidden(Model.SomeHelpMessage), "Something"))
{
<p>To do something, first do something-more-specific, then do another-something-more-specific.</p>
<p>Also, keep in mind that you might need to do something-else-entirely if blah-blah-blah.</p>
}
I haven't found any way to move the "embedded HTML" into a partial view exactly, but a slightly more-friendly way to encapsulate the HTML in a way that provides HTML and Razor syntax highlighting and Intellisense is to move into a view helper function in a file under the app App_Code folder as described in this post on "Hugo Bonacci's Blog".
Here's my helper function:
#helper HelpTextMessage(bool isHidden, string heading, Func<object, object> content)
{
<div class="help-text #(isHidden ? "help-text-hidden" : "")">
<div class="help-text-heading">
#heading
</div>
<div class="help-text-body">
#content(null)
</div>
</div>
}
Assuming the above helper function is in a file named ViewHelpers.cshtml in the App_Code folder, it can be called in a view like this:
#ViewHelpers.HelpTextMessage(false, "Something",
#:To do something, first do something-more-specific, then do another-something-more-specific.
)
or this:
#ViewHelpers.HelpTextMessage(false, "Something",
<p>To do something, first do something-more-specific, then do another-something-more-specific.</p>
<p>Also, keep in mind that you might need to do something-else-entirely if blah-blah-blah.</p>
)
I like having the embedded HTML in a view more than I do being able to use the #using(Html.HelpTextMessage(...){ ... } syntax, so I'm pretty happy with this as a solution.

How to TryUpdateModel from outside of Controller in MVC3

My app has modules that can be turned on and off and these modules are contributing to a view via Html.Partial calls. When the page posts back to the controller I want to have the modules take care of their individual models using something like TryUpdateModel that the controller has. Problem is that TryUpdateModel is a protected method and not accessible from outside the controller.
How can I do something like Controller.TryUpdateModel from a class outside of the controller?
If I am reading this right, it sounds like you are wanting a partial view to update itself.
I have done something similar with some jQuery, by calling an action and returning a partial view inside of a partial view. Inception?
Simple Example. - really simple
_partialViewStart.cshtml
<div id="partialFillerResult">
</div>
<script type="text/javascript">
$(document).ready(function() {
loadPartialViewFiller();
});
function loadLatestTribes() {
$("#partialFillerResult").load("#Url.Action("PartialViewFiller", "Home")").fadeIn("slow");
setTimeout(loadPartialViewFiller, 5000);
}
</script>
HomeController.cs
public ActionResult PartialViewFiller()
{
var yourModel = new ExpandoObject();
if (yourModel == null) return PartialView("_empty");
return PartialView("_partialViewFiller", yourModel);
}
_partialViewFiller.cshtml
#model dynamic
<div class="objectWrapper">
<p>
#Model.Name
</p>
</div>

Why would this partial view return a blank?

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"); }

Multiple if statements in an html attribute - MVC razor

If I wanted multiple if statements in an html attribute I might do something like this:
<input type="button" value="Bad, the title has a lot of excess spacing" title="#if(SomeModel.condOne) {
<text>this</text>
}
#if (SomeModel.CondTwo)
{
<text> is</text>
}
#if (SomeModel.CondThree)
{
<text> a title</text>
}
" />
But that creates a lot of empty spaces that need truncating. So this works:
<input type="button" value="Good, the title is condenced" title="#if(SomeModel.condOne) {<text>this</text>}#if (SomeModel.CondTwo){<text> is</text>}#if (SomeModel.CondThree){<text> a title</text>}" />
The same principle can be applied to an element with multiple classes (e.g. class="oddrow class1" -> class="evenrow class2")
But that might be hard to read if it's a long line. And visual studio has a habit of breaking that statement into multiple lines if you touch the bracket or Ctrl-K,Ctrl-D (which any next developer is likely to do).
Is there a better or more fullproof way to implement multiple attribute conditions in a line for MVC razor?
I suggest creating a small helpers method that returns the text you need.
You'd have to pass it SomeModel and inside that method check for your condition that way you'd have something nicer to look at and easier to maintain.
For example:
public static class HtmlHelpers
{
public static string FetchTitle(this HtmlHelper helper, SomeModel model)
{
//Your logic here.
}
}
You can read all about Html Helper methods here on Jon Galloway's blog.
That's where I learned how to use them.
Why not just do it as:
title="#if(SomeModel.condOne) { <text>this</text> }
#if (SomeModel.CondTwo) { <text> is</text> }
#if (SomeModel.CondThree) { <text> a title</text> }
" />
Helper makes sense if you do use this same logic alot, especially assuming the same model, but you may want to also consider a helper that uses a Func<> expression or Action<> expression. This way, it wouldn't be tied to one model.

MVC3 is it possible to serve a view section from a controller action?

Suppose I have index.cshtml
#{
ViewBag.Title = "Index";
}
#model SomeModel
#section JS{
content1
content2
content3
}
<div> View Content </div>
Is there any way I could have a controller action that would serve ONLY the section JS for a request for index.js?
Such that navigating to http://somesite/index.js would return
content1
content2
content3
Edit: Some further thoughts on this. My goal would be along the lines say creating a layout page that requires a JS section programmatically, and then composing the View to that layout page and then returning the results of this.
Psuedo code example:
var layout = new LayoutPage();
layout.DefineSection("JS", required: true);
layout.Compose(View("index"))
return layout;
I'm not set on achieving that with what I described but I feel that might offer some more insight on what I'd like to achieve.
You can do something like this (but you'd have to write your own controller action to do it properly)
Index.cshml
#model MvcApplication1.Models.TestModel
#{
ViewBag.Title = "Home Page";
}
<h2>#ViewBag.Message</h2>
<p>
To learn more about ASP.NET MVC visit http://asp.net/mvc.
</p>
#section JS {
blahblahblah
}
JSLayout:
#RenderSection("JS")
Your controller Action
public ActionResult Index() {
return View("Index", "_JSLayout", yourModel);
}
This will output only the JS section. If you want to do it programatically then it will take a bit.
The only way to do it would be to make the content of that section into a partial view, and return the partial view from the controller action.

Resources