Declarative AJAX "Controls" in MVC - ajax

I want to create a reusable ajax control in MVC .NET using RAZOR.
my example is a simple ajax text box and list where the user filters the list by typing in the text box. on the first call i would render both the text box and the list using my razor view. on subsequent AJAX calls i would want to ONLY render the (now filtered) list.
idea 1: use #if statement to conditionally render code.
problem: razor does not seem to like conditionally written html. for example it errors when a <div> tag is not followed by a closing </div>.
idea 2: use #section tokens to create portions of my control and then call RenderSection within the same file as needed.
problem: razor does not allow RenderSection to call sections in the same page
i know i can conditionally render html as strings, but i wanted to take advantage of the legibility of the razor markup and keep with development protocols.

You should be able to output <div> tags in a Razor block without the corresponding </div> tag by surrounding it with <text>. The reason is that Razor uses the closing tag to know when to drag back into code-parsing mode:
#if (myCondition)
{
<text>
<div>
</text>
}
As for the Section stuff, you might be able to achieve what you want using Templated Razor Delegates, like this:
#{
Func<dynamic, object> b = #<strong>#item</strong>;
}
// ...
<span>This sentence is #b("In Bold").</span>
See Phil Haack's blog for a little more on this.

Related

Custom Html.ValidationSummary()

I'm having problems the default Html.ValidationSummary() in MVC 3.
As default it adds this code:
<ul>
<li style="display:none"></li>
</ul>
And that empty <ul> causes space I would like to get rid of.
Is there some way to work around this problem? Make it toggle some div around it or similar?
how about conditionally showing ValidationSummary
if(!ViewData.ModelState.IsValid)
{
#Html.ValidationSummary()
}
important if you do this you won't be able to use client-side javascript validation (as the div wont be present)
You can create your own validation summary, for example, like here: Custom ValidationSummary template Asp.net MVC 3

MVC 3 HTML 5 and HTML 4

I have a MVC 3 project and I enable the HTML 5 markup. For the HTML 5 part, it is running fine.
Now I created a partial view and copy and paste some code into it
The first line is
<div id="Header">
I want to use this partial view in my view which is html 4 markup.
The problem comes, the razor engine automatically convert my
<div id="Header">
into
<Header>
I don't want to use HTML 5 for this view but only HTML 4. What should I do?
If you change the div as follows, it won't get swapped out:
<div id="strap">
Which may solve your immediate problem.
why do you want to covert back to:
<div id="Header">
where is the way to go in the future?
If you worried about the compatibility with the older browser, you can simply implement modernizr-2.6.2.js. (which should come with the Visual Studio web projects)
This will make all the basic HTML5 works in older browser.
(tho haven't tested with browser older than IE6)
you could always use a class instead of an id
<div class="header">
this has the added advantage of not making your css (if any) for this element very specific, and also means that the ID cannot be reused.
you can still select your element using jQuery selector using it's class as the selector
$('.header')
question for you: Did you created the Html 4 partial view in Html 5 view? ; If your answer is yes, the problem you mentioned is occurring naturally. When MVC renders your page, he first renders the Html 5 part(the layout master page). As a result, Html5 type doc type will be chosen by default. After that when the Html 4 partial view is rendered, the engine renders it under a mark up support for Html 5.
if i want to summarize what i wanted to say:
<html>
//Html 4 partial view.
</html>
This will make a Html 5 markup view no matter what Html4 code you wrote in that partial view. If i am wrong, let me know. I will learn from my mistakes. thanks.
Can you please use Transitional doctype on the top of your partial view page. Because HTML engine understand the page according to doctype.

When in Editor Template, how can I put javascript in the head section?

I hava an editor template for, let's say, date:
#model DateTime
#section AdditionalJavaScript2
{
/* some js code */
}
#Html.TextBox("", Model.ToString("d.M.yyyy"), new { #class = "date" })
Now, I would like to put some js code into the HEAD section, but this doesn't work.
Of course, I have a this section in my layout.cshtml:
<head>
...
#RenderSection("AdditionalJavaScript2", required: false)
</head>
It works from the plain view, but not from partial view (editor template).
Why?
And, is there a workaround?
Thanks,
Igor
A partial-view does not use a template, it returns "raw" html to be included in your page (by Javascript). It does not have access to anything but the stream it returns itself.
Think of it like this: You typically call a partial view from Javascript/AJAX to get some new html. You get the return, and replace some DIV-tag. How can the system (FireFox, Chrome, ...) know, that there is some extra section of data that needs to replace something in the HEAD tag.
There are some workarounds:
Don't put the script in the HEAD
Add a parameter switch betweed the html and the script. You need to client-side calls, one to get the html, and one for the script. You include the calls to the partial-view on two locations on your page.
Separate the script and the html using some pre-defined tag like <!-- SEPERATOR -->, and let the calling code split the result, and put it in the correct position.

How to modify body class in MVC3 view page

Just wanted to add a class="myClass" in body tag. Is there any html helper or something else can do this in MVC3 view page? Please advise, thanks.
This is very similar to Aaron's solution, but doesn't have the weight of a section (which at least in my mind, are for larger blocks of content than a single string). The simplest way is to pass a variable with the ViewBag.
In your layout, just print out the class for the body tag, plus any other page specific variables (page title, extra css/js scripts, etc...)
_Layout.cshtml:
<html>
<title>#ViewBag.Title</title>#* Can easily add in per page titles too *#
<body class="#ViewBag.BodyClass">
#RenderBody()
</body>
</html>
Then, variables set in your view get passed upwards to the layout:
Index.cshtml:
#model MyViewModel
#{
ViewBag.Title = "This page title!";
ViewBag.BodyClass = "...";
}
While you may have full control of the HTML a solution was what was needed so here is one ;-)
In the _layout.cshtml page
<body class="#RenderSection("BodyClass", false)">
This will look for a section in all the child pages but says don't worry if it can't find one
Then in your child views just do this
#section BodyClass {productList}
Keep it on one line and then the outputted HTML will look fine, also you can then build up the class names as well.
#section BodyClass {productList generic}
This idea goes perfect with DOM-Ready page specific code, why not checkout
http://paulirish.com/2009/markup-based-unobtrusive-comprehensive-dom-ready-execution/
Or my extended version here
https://github.com/AaronLayton/H5BP-Core
My way lets you do page specific code, but allows you to keep all of the Javascript in separate pages so each page becomes easily manageable. The final step would be to concatenate and minify all the JS into 1 file ;-)

Razor Nested Layouts with Cascading Sections

I have an MVC3 site using Razor as its view engine. I want my site to be skinnable. Most of the possible skins are similar enough that they can derive from a shared master layout.
Therefore, I am considering this design:
However, I would like to be able to call RenderSection in the bottom layer, _Common.cshtml, and have it render a section that is defined in the top layer, Detail.cshtml. This doesn't work: RenderSection apparently only renders sections that are defined the next layer up.
Of course, I can define each section in each skin. For instance, if _Common needs to call RenderSection("hd") for a section defined in Detail, I just place this in each _Skin and it works:
#section hd {
#RenderSection("hd")
}
This results in some duplication of code (since each skin must now have this same section) and generally feels messy. I'm still new to Razor, and it seems like I might be missing something obvious.
When debugging, I can see the complete list of defined sections in WebViewPage.SectionWritersStack. If I could just tell RenderSection to look through the entire list before giving up, it would find the section I need. Alas, SectionWritersStack is non-public.
Alternatively, if I could access the hierarchy of layout pages and attempt execution of RenderSection in each different context, I could locate the section I need. I'm probably missing something, but I don't see any way to do this.
Is there some way to accomplish this goal, other than the method I've already outlined?
This is in fact not possible today using the public API (other than using the section redefinition approach). You might have some luck using private reflection but that of course is a fragile approach. We will look into making this scenario easier in the next version of Razor.
In the meantime, here's a couple of blog posts I've written on the subject:
http://blogs.msdn.com/b/marcinon/archive/2010/12/08/optional-razor-sections-with-default-content.aspx
http://blogs.msdn.com/b/marcinon/archive/2010/12/15/razor-nested-layouts-and-redefined-sections.aspx
#helper ForwardSection( string section )
{
if (IsSectionDefined(section))
{
DefineSection(section, () => Write(RenderSection(section)));
}
}
Would this do the job ?
I'm not sure if this is possible in MVC 3 but in MVC 5 I am able to successfully do this using the following trick:
In ~/Views/Shared/_Common.cshtml write your common HTML code like:
<!DOCTYPE html>
<html lang="fa">
<head>
<title>Skinnable - #ViewBag.Title</title>
</head>
<body>
#RenderBody()
</body>
</html>
In ~/Views/_ViewStart.cshtml:
#{
Layout = "~/Views/Shared/_Common.cshtml";
}
Now all you have to do is to use the _Common.cshtml as the Layout for all the skins. For instance, in ~/Views/Shared/Skin1.cshtml:
#{
Layout = "~/Views/Shared/_Common.cshtml";
}
<p>Something specific to Skin1</p>
#RenderBody()
Now you can set the skin as your layout in controller or view based on your criteria. For example:
public ActionResult Index()
{
//....
if (user.SelectedSkin == Skins.Skin1)
return View("ViewName", "Skin1", model);
}
If you run the code above you should get a HTML page with both the content of Skin1.cshtml and _Common.cshtml
In short, you'll set the layout for the (skin) layout page.
Not sure if this will help you, but I wrote some extension methods to help "bubble up" sections from within partials, which should work for nested layouts as well.
Injecting content into specific sections from a partial view ASP.NET MVC 3 with Razor View Engine
Declare in child layout/view/partial
#using (Html.Delayed()) {
<b>show me multiple times, #Model.Whatever</b>
}
Render in any parent
#Html.RenderDelayed();
See the answer link for more use-cases, like only rendering one delayed block even if declared in a repeating view, rendering specific delayed blocks, etc.

Resources