Unable to display validation in partial view - asp.net-mvc

I am using the code from the below link. It works fine . But though there are validation errors, and ValidationSummary(true/false) is enabled, I am not able to see the validation message.
ASP.NET MVC Partial view ajax post?
As a work around ,When I try to display error message explicitly using the below code, it still does not display .When in debug mode, the ModelState has the error message , but it does not display .
<div>
#{
foreach (var i in ViewData.ModelState.Values)
{
<ol>
#{
if(i.Errors != null && i.Errors.Count>0)
{
var error = i.Errors[0];
<li>error.ErrorMessage</li>
}
}
</ol>
}
}
</div>
Please help.

You can use #Html.ValidationMessage html helper to display property-level validation message in your partial view.

Related

Changes to VM after POST not reflected in the Page [duplicate]

I want to send a message to userID=3 by going to /MyController/Message/3
This executes Message() [get] action, I enter some text in the text area and click on Save to post the form
Message() [post] action saves the changes, resets the value of SomeText to empty string and returns to the view.
At this point I expect the text area to be empty because I have set ViewData["SomeText"] to string.Empty.
Why is text area value not updated to empty string after post action?
Here are the actions:
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Message(int ID)
{
ViewData["ID"] = ID;
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Message(int ID, string SomeText)
{
// save Text to database
SaveToDB(ID, SomeText);
// set the value of SomeText to empty and return to view
ViewData["SomeText"] = string.Empty;
return View();
}
And the corresponding view:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm())
{ %>
<%= Html.Hidden("ID", ViewData["ID"])%>
<label for="SomeText">SomeText:</label>
<%= Html.TextArea("SomeText", ViewData["SomeText"]) %>
<input type="submit" value="Save" />
<% } %>
</asp:Content>
The problem is that your ModelState is re-filled with the posted values.
What you can do is clear it on the Action that has the Post attribute :
ModelState.Clear();
The problem is the HtmlHelper is retrieving the ModelState value, which is filled with the posted data. Rather than hacking round this by resetting the ModelState, why not redirect back to the [get] action. The [post] action could also set a temporary status message like this:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Message(int ID, string SomeText)
{
// save Text to database
SaveToDB(ID, SomeText);
TempData["message"] = "Message sent";
return RedirectToAction("Message");
}
This seems to me like more correct behaviour.
The html helpers read the value from the ModelState. And there's no elegant way to override this behaviour.
But if you add this line after SaveToDB(ID, SomeText), it should work :
ModelState["SomeText"].Value =
new ValueProviderResult("", "", CultureInfo.CurrentCulture);
I tried everything, but only worked when I did something like this:
ModelState.Clear();
//This will clear the address that was submited
viewModel.Address = new Address();
viewModel.Message = "Dados salvos com sucesso!";
return View("Addresses", ReturnViewModel(viewModel));
Hope this helps.
Instead of using ModelState.Clear() which clears the whole modelstate, you can do ModelState.Remove("SomeText"), if you want to. Or render the Input without the htmlhelper-extensions.
They are designed to take the Value from ModelState instead of the Model (or viewdata).
That is a clientside behavior. I would recommend using javascript. If you use JQuery, you can do it like this:
<script type="text/javascript">
$(function(){ $("#SomeText").val("");});
</script>
I don't use Javascript anymore, but I believe in regular JS that it is like:
document.getElementById("SomeText").value = "";
(You would do this on one of the load events.
<body onload="...">
Hope this helps.
I am fairly certain the textarea is grabbing the value from the Request.Form under the hood since ViewData["SomeText"] is empty.
Is it possible that the model state has been updated with an error? I believe that it will pull the attempted value from the model state rather than from view data or the model if the model state isn't valid.
EDIT:
I'm including the relevant section of the source code from the TextArea HtmlHelper extension below. It appears to me that it does exactly what I expected -- if there has been a model error, it pulls the value from the model state, otherwise it uses it from ViewData. Note that in your Post method the "SomeText" key shouldn't even exist until you set it, i.e., it won't be carried forward from the version of the code that responds to the GET.
Since you explicitly supply a value to the ViewData, useViewData should be false, attemptedValue should be false unless an error has been set in the model state.
// If there are any errors for a named field, we add the css attribute.
ModelState modelState;
if (htmlHelper.ViewData.ModelState.TryGetValue(name, out modelState)) {
if (modelState.Errors.Count > 0) {
tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
}
}
// The first newline is always trimmed when a TextArea is rendered, so we add an extra one
// in case the value being rendered is something like "\r\nHello".
// The attempted value receives precedence over the explicitly supplied value parameter.
string attemptedValue = (string)htmlHelper.GetModelStateValue(name, typeof(string));
tagBuilder.SetInnerText(Environment.NewLine + (attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(name) : value)));
return tagBuilder.ToString(TagRenderMode.Normal);
Do s.th. like this:
add:
ModelState.Clear();
before the return statement of the submit buttons action method. Works for me. It could work for you.

dropzone.js and ASP.NET MVC file posted is null?

I am trying to use dropzone.js to upload images in my ASP.NET MVC app. I am able to set-up the dropzone programatically, click on it, select the image and when I click "Open" in the file dialog, the correct Action is hit in the controller. However, the HttpPostedFileBase always comes back as null so I can't do anything with the image. ON the client-side, however, it shows the image thumbnail correctly, eventhough I can't get it on the server side.
This is the HTML:
<div style="float:left;margin-right:2px;" id="mainImage">
<img src="/images/AddImage_button.png" class="dz-message" />
</div>
This is the js code I call after the doc is ready:
var myDropzone = new Dropzone("div#mainImage", { url: "/Market/UploadImage" });
And this is the action call inside of the controller:
public ContentResult UploadImage(HttpPostedFileBase imageFile)
{
if (imageFile == null || imageFile.ContentLength == 0)
{
//.....
}
}
The action is hit but imageFile is null. Does anyone has any ideas? By the way, the "dz-message" class was added in the image placeholder inside the dropzone because before that it was not clickable. I read it somewhere that was a fix for that issue and it worked.
Any ideas why I am getting null for imageFile?
Default parameter name that Dropzone uses is file, and yours is imageFile. Change imageFile to file and it will work
There is a small tweak you may miss.
Happened to me lots of times,
The form element you use, must have it's enctype attribute set like this:
<form action="~/Home/SaveUploadedFile" method="post" enctype="multipart/form-data"/>

Partial Views & ModelState.AddModelError

the source of LoginRegister view is like this :
#Html.Partial("authentication/_login")
#Html.Partial("authentication/_register")
and each child view has got a form with this syntax
#using (Html.BeginForm(**seperated-methods**, "Login"))
{
#Html.ValidationSummary(false)
}
I send error(s) in postback whit this code
ModelState.AddModelError("", "**any-error-message**");
return View("authentication/LoginRegister", customized-data);
The point is , error message shows in both partial views.
You need to tell the ModelState to which property this error refer to:
ModelState.AddModelError("PropertyName", "**any-error-message**");
Now it will be only in the
#Html.ValidationMessageFor(m => m.PropertyName)
If you don't specify the property name, the error will be considered global and get shown in every ValidationSummary.

How to remove list from validation summary

I added ValidationSummary Html helper for my View Model class which has 5 required fields. And it works got nice red words missing 1, missing 2 etc.
But I need to display just one message not five of them (something like: "Your input is not valid."). Can this be done with ValidationSummary?
You have two options (at least):
Either use the validation summary and exclude property errors:
#Html.ValidationSummary(true, "The input is not valid")
or associate a error message with a custom key in your action:
if (!ModelState.IsValid)
{
ModelState.AddModelError("myerrorsummary", "The input is not valid");
}
and display it on your page:
#Html.ValidationMessage("myerrorsummary")
You can try skipping the helpers if all you want to do is simply display a message if the ModelState is not valid. Simply check the ModelState within ViewData and that should work.
#if (!ViewData.ModelState.IsValid)
{
<p>Your input is not valid.</p>
}
If you look at MVC3 source code you'll see that, currently, if you use ValidationSummary with excludePropertyErrors=true while having UnobtrusiveJavaScriptEnabled, there won't be any validation summary rendered.
I was able to display just a single message with MVC3 with UnobtrusiveJavascript enabled, for client side validation. Don't use #Html.ValidationSummary at all, and render:
#{
//Show the message when there are server side errors
ViewBag.ValidationSummaryClass = ViewData.ModelState.IsValid ? "validation-summary-valid" : "validation-summary-errors";
}
<div class="#ViewBag.ValidationSummaryClass" data-valmsg-summary="true">
<span>Before you can continue, please make sure you have completed the mandatory fields highlighted above.</span>
<ul style="display:none"/>
</div>
Notice the display:none, unobtrusive javascript still fills the list with error messages, but they are kept hidden.
One brute force approach I've used in MVC3:
if (!ModelState.IsValid)
{
ModelState.AddModelError("", "Some contextual error message");
}
and display it on your page:
<% if(!ViewData.ModelState.IsValid) { %>
<span class="error"><%=ViewData.ModelState[String.Empty].Errors[0].ErrorMessage %> </span>
<% } %>

Internet Explorer Post Data Bug - ASP.NET MVC

I just started playing with MVC and I've run into a roadblock. I'm using a partial view as a User Login flyout on the header of each page using OpenID. When the user clicks on the provider (similar to stackoverflow) it authenticates and then either returns to the calling page or redirects to the signup page. The code works flawlessly under Firefox and Chrome but bombs out in IE. The "provider" parameter in the controller is always sent as null. Is there some sort of bug involving posting input names/values in IE or am I doing something wrong?
This is what my openid partial view looks like:
<% using (Html.BeginForm("Authenticate", "Membership", new { ReturnUrl = Request.Url }, FormMethod.Post))
{
if (!Page.User.Identity.IsAuthenticated)
{ %>
<div class="openidProviders">
Log in or join using one of these OpenID providers:
<div class="large buttons">
<div class="provider"><div><%= Html.SubmitImage("provider", "/Content/common/images/google.gif", new { value = "Google" })%></div></div>
<div class="provider"><div><%= Html.SubmitImage("provider", "/Content/common/images/Yahoo.gif", new { value = "Yahoo" })%></div></div>
<div class="provider"><div><%= Html.SubmitImage("provider", "/Content/common/images/AOL.gif", new { value = "AOL" })%></div></div>
<div class="provider"><div><%= Html.SubmitImage("provider", "/Content/common/images/OpenId.gif", new { value = "OpenId" })%></div></div>
</div>
</div>
<% }
}
%>
And the controller logic is here:
[AcceptVerbs(HttpVerbs.Post), ValidateInput(false)]
public void Authenticate(string provider, string ReturnUrl)
{
// Figure out provider endpoint
// Authentication function calls here
}
Well, it looks like IE, for once, is the only browser properly following the HTML spec according to this post.
The HTML specification only requires
that x, y coordinates where the image
submit button was clicked be sent to
the web server. IE follows the
specification. The browsers that send
the value="..." parameter are doing
their own thing outside of the HTML
specification.
Basically, I need to use a submit input instead of SubmitImage and then style the background of the button accordingly. Not the optimal solution but at least it works. This is what the final solution looks like. If anyone knows a way of getting the SubmitImage to work properly, let me know.
Replace the buttons above with ones that look like this:
<input type="submit" value="Google" class="google_OpenID" name="provider" />
And the CSS class:
.google_OpenID
{
background-image: url(/Content/common/images/google.gif);
width:75px;
cursor:pointer;
color:transparent;
height:35px;
border:none;
}

Resources