MVC 4 HiddenFor field not appearing in rendered markup - asp.net-mvc

Am using MVC 4 and want to maintain some values on postback, so they're going into hidden fields. In essence:
#using (Html.BeginForm())
{
Html.HiddenFor(model => model.EventId);
Html.HiddenFor(model => model.paymentMethodId);
}
But the hidden fields are not appearing in the rendered markup and are therefore - obviously - missing on postback.

You need to add a #, #Html.HiddenFor(). Otherwise you're just executing the helper method, but not actually doing anything with the output.

As dombenoit says, missing the "#" directive, and also need to remove the ";" from the end of each line for some reason, so the corrected code sample looks like:
#using (Html.BeginForm())
{
#Html.HiddenFor(model => model.EventId)
#Html.HiddenFor(model => model.paymentMethodId)
}
Now renders the hidden fields as expected.

Related

Razor not rendering multiple Html.BeginForm()

I have a razor page that uses T4template. Here is my razor code:
#model ResearchViewModel
<form method="POST" action=">
...
#if (!Model.IsFinalized)
{
using (Html.BeginForm(MVC.Research.ActionNames.Reject, MVC.Research.Name, null, FormMethod.Post, new { #id = "RejectForm" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.Id)
}
using (Html.BeginForm(MVC.Research.ActionNames.Accept, MVC.Research.Name, null, FormMethod.Post, new { #id = "AcceptForm" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.Id)
}
}
...
</form>
The problem is that when the razor rendering this page, it cannot rendering first form !! I tried to change the sequence of these forms, and found that always the first form is not rendered. I Also tried to separate these forms using the partialview but the problem still exist. Does anyone knows that what's happening ?
You are trying to nest multiple forms and you can't do that. See this link for an explanation: Can you nest html forms?
You need to remove your starting HTML
<form method="POST" action=">
because you can't have other forms inside them. I would guess that closing tag of your first form created by razor Html helper is closing this tag, so you can see the other form created by second razor Html helper

Applying CSS class to Html.DisplayFor (ASP.NET MVC)

Am new to MVC, am am trying to apply CSS styles to Html.DisplayFor helper inside my template file: Shared>>EditorTemplate>>Contacts.cshtml. Below is my code:
#model People.Contacts
<div>
#Html.DisplayNameFor(m => m.Name) <span class="myclass">#Html.DisplayFor(m => m.FirstName) #Html.DisplayFor(m => m.LastName)</span></div>
and my css class outside this template looks like this:
.myclass{font:italic bold;}
Html.DisplayFor does not support passing HTML attributes, including class/style. At it's most basic it merely renders the value, without any HTML, and with editor/display templates, it just renders whatever's in the template.
First, if you have EditorTemplates\Contacts.cshtml, that will actually never be used by DisplayFor. For DisplayFor you need a separate template in Views\Shared\DisplayTemplates. As its name implies EditorTemplates is used by EditorFor.
Either DisplayFor or EditorFor are basically the same as calling Html.Partial. There's just some additional logic to deal with a specific model property and look by default in DisplayTemplates/EditorTemplates for the view. That said, you can pass additional data to them the same as you would with a partial, via ViewData.
For example, if you were to call #Html.DisplayFor(m => m.FirstName, new { #class = "myclass" }), then nothing would happen by default, but you would have a value of "myclass" in ViewData["class"]. You could then use that to modify a part of your template. For example:
Views\Shared\DisplayTemplates\Contacts.cshtml
<span #(ViewData["class"] != null ? "class='" + ViewData["class"] + "'" : string.Empty)>
#ViewData.TemplateInfo.FormattedModelValue
</span>
That checks to see if ViewData["class"] has a value, and if so, adds a class attribute with that value to the span.
As a different solutions you can use Html.DisplayFor in <Label> tag
<label class="control-label"> #Html.DisplayNameFor(p => p.HeadLine)</label>

MVC Razor Form Validation from Render Action

I am new to MVC and trying to implement what I would expect to be a common problem. I have a simple search form that I want to implement on each page of the site. I want this section to maintain its own code so that I don't have to duplicate it on each page.
So far I have been able to do this by calling a render action on the template page. The render action populates the quicksearch form. When I submit the form I am able to validate the form, however I have not found a way to redisplay the same page with the validation information. I would prefer a way that would just refresh the form area, but I would accept a full postback as long as the page is redisplayed.
Template Render Call
#{Html.RenderAction("Display", "QuickSearch");}
ActionController
[HttpPost]
public ActionResult Submit(QuickSearchModel qsModel)
{
if (!ModelState.IsValid)
{
return PartialView(qsModel);
}
//Perform redirect
}
[ChildActionOnly]
public ActionResult Display()
{
//populate model
return View(qsModel);
}
Quick Search View
<div>
#using (Html.BeginForm("Submit", "QuickSearch"))
{
#Html.ValidationSummary(true)
#Html.LabelFor(m => m.Destination)#Html.EditorFor(m => m.Destination)#Html.ValidationMessageFor(m => m.Destination)<br />
#Html.LabelFor(m => m.ArrivalDate)#Html.EditorFor(m => m.ArrivalDate)#Html.ValidationMessageFor(m => m.ArrivalDate)
#Html.LabelFor(m => m.DepartureDate)#Html.EditorFor(m => m.DepartureDate)#Html.ValidationMessageFor(m => m.DepartureDate)<br />
#Html.LabelFor(m => m.Adults)#Html.DropDownListFor(model => model.Adults, new SelectList(Model.AdultsSelectOptions, "value", "text", Model.Adults))<br />
#Html.LabelFor(m => m.Children)#Html.DropDownListFor(model => model.Children, new SelectList(Model.ChildrenSelectOptions, "value", "text", Model.Children))<br />
<input id="qsSubmit" name="qsSubmit" type="submit" value="Submit" />
}
</div>
Thanks in advance for any assistance!
I see that you have the following problems:
How to redirect back to the page, from which the search was made?
What if this original page was "POSTed to" - that is it was rendering something, based on POST request? In this case we will not
be able to "re-produce" this POST in any easy way;
After we have redirected to the original page, how to communicate the search model (or just it's errors), which we have failed to
validate?
Given all these challenges, I would first seriously consider making this search form in AJAX style. That would be much easier solution, if it fits you.
If AJAX is not an option I see following solutions to the respective questions:
I would make a hidden field in the search form with the URL of original page. When validation fails, we can redirect to this URL (just check that it is local URL and no one tries to brake something);
This is a major problem - trying to replay original POST is not easy, but it may not be needed either - just check if this is a problem anyway;
You could use TempData dictionary to communicate errors or model back to original page.

Asp.Net Mvc 3 Client Validation, Attributes generation

Asp.net Mvc3 ads some custom attributes like "data-val-required" on input elements to perform validation. I know all theory behind this, how it works.
What i want to know is :
When I create my form inside " #using (Html.BeginForm())" it produces custom attributes, but it doesn't create those attributes when i place my form between plain "<form>" tag.
below is a demo i have created to demonstrate what iam saying
Razor Code, form inside BefingForm()
#using (Html.BeginForm()) {
#Html.EditorFor(model => model.EmailAddress)
#Html.ValidationMessageFor(model => model.EmailAddress)
}
generated Html contains "data-val-required" as attribute shown below
<input type="text" value="" data-val-required="The Email Address field is required." data-val-email="my message">
Razor Code Form inside pure Html Tag
<form action="/Account/Register" method="post">
#Html.EditorFor(model => model.EmailAddress)
#Html.ValidationMessageFor(model => model.EmailAddress)
</form>
generated Html doesnt contain "data-val-required" attribute shown below
<input type="text" value="" gtbfieldid="44">
My question is how can i ask MVC to add those attributes even form is placed in side pure html tags
I believe BeginForm method internally assigns a formcontext object to viewCotnext's property FormContext. If you do not want to use plain html form tags you have to do it manually like
<%
this.ViewContext.FormContext = new FormContext();
%>
and in razor it would probably be
#{
this.ViewContext.FormContext = new FormContext();
}
Problem here is that internally Html.BeginForm is flagged by Html.EnableClientValidation() to create FormContext that will store client-side validation metadata. Now, any HTML helper method that renders validation message also registers appropriate client-side validation metadata in FormContext. The result is what you get if you use helper. However, if you try to use HTML syntax and not helpers, the FormContext is never registered and therefore your validation is never added.
Regards,
Huske

RenderPartial control in same view folder

I have a file in my view folder Users called UserViewControl.cshtml.
My code in the actual view (Users.cshtml) is:
#Html.RenderPartial("RegisterViewControl")
Error:The best overloaded method match for 'System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)' has some invalid arguments
I do not want to type the path fully like this as the whole view folders might move in the future:
#Html.RenderPartial("~/Views/Users/RegisterViewControl.cshtml")
Code in RegisterViewControl.cshtml:
#model SampleMVC.Web.ViewModels.RegisterModel
#using (Html.BeginForm("Register", "Auth", FormMethod.Post, new { Id = "ERForm" }))
{
#Html.TextBoxFor(model => model.Name)
#Html.TextBoxFor(model => model.Email)
#Html.PasswordFor(model => model.Password)
}
This is a form that will be submitted by ajax, but I want all the validation from the viewmodel.
It should be like this:
#{Html.RenderPartial("RegisterViewControl");}
And that's because the RenderPartial extension method doesn't return anything. It writes directly to the output. In aspx you use it like this:
<% Html.RenderPartial("RegisterViewControl"); %>
instead of:
<%= Html.RenderPartial("RegisterViewControl") %>
So the same rules apply for razor.
You could alternatively use
#Html.Partial("RegisterViewControl")
I had this issue as well and got this directly from Scott Guthrie's blog post:
using #Html.RenderPartial() from a Razor view doesnt work.
Rather than call Html.RenderPartial() use just
#Html.Partial("partialname")
That returns a string and will work.
Alternatively, if you really want to use the void return method you
can use this syntax:
#{Html.RenderPartial("partialName")}
But #Html.Partial() is the cleanest.
The link for this is: http://weblogs.asp.net/scottgu/archive/2010/12/30/asp-net-mvc-3-layouts-and-sections-with-razor.aspx

Resources