I'm rendering some input controls dynamically. I wrote a method like this
public override MvcHtmlString GetActionControl(HtmlHelper<ItemDetailsViewModel> helper)
{
return
helper.EditorFor(A => A.Triage.ProcessNumber) +
helper.ValidationMessageFor(a => a.Triage.ProcessNumber, "*")
}
And I'm calling this from the main CSTHML file like this:
<!-- Render Action Controls for each possible action -->
#foreach (IActionControl iac in WorkflowActionControls.GetActionControls(Model.WorkflowItem.CurrentState))
{
<div id="#("div" + iac.ControlName)" class="ui-corner-all ui-widget ui-widget-content" style="margin-top: 24px; padding: 15px;">
#iac.GetActionControl(this.Html)
</div>
}
Notice that I'm passing the current HtmlHelper to the GetActionControl() method.
Problem is, the generated output is only:
<input class="text-box single-line" id="Triage_ProcessNumber" name="Triage.ProcessNumber" type="text" value="" />
Ie, no "extended" validation fields, and no validation . Aditionally I've discovered that the helper.ValidationMessageFor() method returns NULL.
However, If I put the editor and the validationMessage on the .cshtml directly everything works like a charm:
#Html.EditorFor(a => a.Triagem.ProcessNumber)
#Html.ValidationMessageFor(a => a.Triagem.ProcessNumber, "*")
What am I doing wrong here? Shouldn't the end result of calling HtmlHelper.EditorFor be the same? I'm sorry if this is a lame question but there isn't much information on generating HTML markup dynamically in regards to MVC 3.
I've checked the common pitfalls and everything is OK: validation enabled on web.config, the model class has the proper validation attributes, etc.
Any help would be greatly appreciated :)
PS: I've simplified the pasted code and ommited the form.
I don't know if this will help you, but validation is rendered when Html.ViewContext.FormContext is not null. When i had same problem, i just initialized form context with new FormContext(); and it worked
Related
When I click submit on view, the system redirects to a new view. If validation fails, the system redirects to the same page highlighting the fields. However, I also require the system to show a label with the error message.
<label for="label6" style="color:red; font-weight:normal !important; visibility: hidden">
The Corporate Email, FEIN or SSN does not match.<br /><br />
<span style="margin-left: 10%"></span>The following might be the case:<br />
<span style="margin-left: 12%"></span>- The Corporate Email entered is wrong. Please check the Corporate Email.<br />
<span style="margin-left: 12%"></span>- The FEIN entered is wrong. Please check the FEIN.<br />
<span style="margin-left: 12%"></span>- The SSN entered is wrong. Please check the SSN.<br />
<span style="margin-left: 12%"></span>- Please verify whether FEIN or SSN entered during registration.<br />
<span style="margin-left: 16%"></span>If you have registered using FEIN please submit using FEIN.<br />
<span style="margin-left: 16%"></span>If you have registered using SSN please submit using SSN.<br />
</Label>
Can someone help me with this.
I don't think you want to do it like that. Why tell them what the error might be when you can tell them what the error actually is?
In your view, after each #Html.EditorFor put a #Html.ValidationMessageFor.
#Html.TextAreaFor(a => a.EmailID)
#Html.ValidationMessageFor(a => a.EmailID)
#Html.TextAreaFor(a => a.Password)
#Html.ValidationMessageFor(a => a.Password)
If your model state is invalid and you return to the view, the validation messages are automatically displayed for the invalid fields.
Going further, you can get the validation to be done using JavaScript in the browser, so that if the data is invalid the error message(s) will be displayed without needing a trip back to the server.
Simply add the following to the end of your view:
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
(This assumes your site is based on the standard ASP.NET MVC template, and that you view uses a layout view. If not, you may have to do a bit of tweaking to get the correct JavaScript files.)
WARNING: Never rely solely on browser validation checking. It is there as a benefit to users so they get errors reported slightly faster. However, it is very easy for hackers to bypass browser checking, so always check the model state on the server as well.
If you want exactly that content, then in your controller, when the model is invalid, put
ViewBag.InvalidModel = true;
Then in your view put
#if(ViewBag.InvalidModel)
{
<!-- Your label here-->
}
In controller
public ActionResult Index()
{
if (ModelState.IsValid)
{
//do something
return Redirect("/yournewpage");
}
if (!someChecks)
{
ModelState.AddModelError("", "Your custom error");
}
if (!someChecks2)
{
ModelState.AddModelError("", "Your custom error 2");
}
return View();
}
You can use in view
<p>
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<p>
Suppose I have a field like this:
<div class="form-group">
<label for="fullname" asp-for="UserName">Username</label>
<input class="form-control"
type="text" name="username"
required asp-for="UserName">
<span asp-validation-for="UserName"></span>
</div>
inside my controller I added this error:
ModelState.AddModelError("username", "username already registered");
Now, I want apply the focus on the input field and also I want apply a red border, is possible do this only via MVC?
When the model validation fails and you return to the same view, the framework will add the input-validation-error CSS class to the input elements, for which the validation failed. In your case, you are adding the error message to the UserName field, so your UserName field input will get this new CSS class.
<input class="form-control input-validation-error" type="text" name="username"
required="" id="UserName" value="some value">
You can add any sort of styling you want to this CSS class as needed.
.input-validation-error
{
border-color:red;
}
Now setting the focus on a specific input field is a little tricky. The server code cannot do that. You have to do that on client side. But if there are multiple fields in the form with failed validation, which one you want to focus ? The first one, second one ? last one ?
Here is a quick sample to focus on the first input element with input-validation-error CSS class. The JavaScript code is executed on the jquery document.ready event.
$(function () {
$("input.input-validation-error").first().focus();
});
If you want to style the validation error message rendered by the validation helper (<span asp-validation-for="UserName"></span>), follow the same approach. When validation fails, the framework will change the CSS class of this span element to field-validation-error (from field-validation-valid). So all you have to do is, add the needed style definitions to that CSS class.
.field-validation-error
{
color:red;
}
I have an issue when using a hidden field in an MVC Form Post. When the hidden field is generated via a HTML Helper it won't preserve it's value during the postback. But when using a HTML tag, it works.
Unfortunately this one has taken me a whole day to work out this work around.
Here is what I'm doing... (excuse any spelling, re-typed code for SO):
View Model
public class SomeViewModel
{
public int MyProperty1 { get; set; }
public int MyProperty2 { get; set; }
public int MyProperty3 { get; set; }
}
Post method
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult MyActionMethod(SomeViewModel someViewModel, string command)
{
...
...
// someViewModel.MyProperty1
...
...
}
View
#using (Html.BeginForm("MyActionMethod", "SomeController", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(m => m.MyProperty1)
<div class="col-md-2">
<input type="hidden" value=#Model.MyProperty1 name="MyProperty1" />
<input type="submit" name="command" value="Button1" class="btn btn-primary" />
<input type="submit" name="command" value="Button2" class="btn btn-success" />
</div>
<div class="col-md-1"></div>
<div class="col-md-1">
<input type="submit" name="command" value="Button3" class="btn btn-danger" />
</div>
<div class="col-md-8"></div>
}
In the above View code, the HTML helper hidden field (#Html.HiddenFor(m => m.MyProperty1)) does NOT work. But the HTML tag hidden field (input type="hidden" value=#Model.MyProperty1 name="MyProperty1") DOES work. I only have one or the other enabled. Both shown here are for display purposes.
I'd prefer to use the HTML Helper syntax, but can live with the HTML tag.
Things to note:
The View is using multiple submit buttons.
The View is using a partial view. Currently no content in the partial view and nothing is being done with it.
I can't see how these would affect the issue. Thought I'd mention it, in case.
Question: Can anyone explain why the HTML Helper isn't working?
***** UPDATE *****
Thanks to Stephen Muecke for pointing out what needed to be included in my question. Moreover an extra thank you for guessing what I was actually doing but I couldn't articulate it.
I'm updating the View Model property in the ActionMethod(), and when the same View is re-rendered, the View Model property doesn't reflect the new value.
Rather it is keeping it's initial value, and not preserving the new value.
Although not obvious and I found it difficult to find many articles on this subject to clarify it for me in the past the default behaviour in ASP.NET MVC is the following:
If you are using HTML Helpers and you are rendering the same View in response to a POST it is assumed that you are responding to failed form validation.
Therefore the values before being set in the POST will always be rendered back in the view from ModelState.
You have a few options:
ModelState.Clear(); in your post. Not recommended as the framework has not been designed this way.
Use the Post-Redirect-Get pattern and only display validation failure, as the framework was designed (as #StephenMuecke mentions).
If you are not bothered about validation do not use HtmlHelpers
Use Request.Form values instead and remove the SomeViewModel someViewModel parameter. Wouldn't recommend this as you lose all benefits of model binding.
Use ModelState.Remove for the specific field, again not recommended.
The best article I found on this was article from Simon Ince in 2010:
ASP.NET MVC’s Html Helpers Render the Wrong Value!
Another one by Rick Strahl:
ASP.NET MVC Postbacks and HtmlHelper Controls ignoring Model Changes
I am displaying my 'news' page and I want the customer to be able to output some simple html.
My view looks like this:
#using SuburbanCustPortal.SuburbanService
<br />
#foreach (var item in (IEnumerable<TokenNews>) ViewBag.News)
{
<div class="fulldiv">
<fieldset>
<legend>#item.Title</legend>
<div>
#item.Body
</div>
</fieldset>
</div>
}
When I do it this away, the html isn't being rendered by the browser, it's just showing the html as text.
Any way that I can output the html where the browser will render it?
You didn't exactly specify what part is being shown as text, but if it's item.Body, do #Html.Raw(item.Body) instead. That turns a string into an IHtmlString, whose purpose is to tell Razor that this thing is guaranteed to be safe to output as-is, and will not contain nasties like XSS attacks (ensuring this when using Html.Raw is your job). Everything that is not an IHtmlString will be escaped automatically by Razor.
Html.ActionLink("<span class=\"title\">Retry</span><span class=\"arrow\"></span>", "Login", "User")
Hi,
If I execute above code in ASP.Net MVC 2, I get the following output on my screen:
Error? http://img27.imageshack.us/img27/2069/screenerror.png
How do I disable the escaping of the code, so my span is within the ActionLink, and not displayed as output?
I know this is expected behavior, to keep it safe, but I want it to interpret the HTML code I pass as a parameter.
Thanks!
Yvan
The ActionLink helper method can only be used for plain-text links.
You should manually make an <a> tag, like this:
<a href="<%=Url.Action("Login", "User") %>">
<span class="title">Retry</span><span class="arrow"></span>
</a>
I think the following also works.
<span class="title"><%= html.actionlink("Retry","Login", "User") %></span><span
class="arrow"></span>
I mean, <.span>Retry<./span> is just <.span>plaintext<./span> which is the same as the actionlink text? ("." inserted for SO)