asp.net mvc 3 client validation submitting empty f

2019-09-13 06:24发布

问题:

It appears as if my client validation is not validating properly.

On my log on screen, when I set my username and password and submit the form is cleared and the validation message appears for required fields and the form is not always posted. why do validation clear my fields and say that they are empty?

also sometimes the form is posted but with blank fields so model binding fails on the server

the even weirder part is that i have disabled client side validation and still it fails on my production server

Everything is fine in dev

Update : my action are already seperated, even different action names

[HttpGet]
        public ActionResult LogOn()
        {
            LogOnModel model = new LogOnModel() { UserName = "", Password = "" };
            return View(model);
            //return View();
        }

  [HttpPost]
  public ActionResult LogIn(LogOnModel model, FormCollection fcol/*, string returnUrl*/)
        {
            //Request.Form.Count
            StringBuilder sb = new StringBuilder();
            sb.Append("<br/>Form collection: ");
            if (Request.Form.Count > 0)
            {

                NameValueCollection form = Request.Form;
                sb.Append("<Form collection>");
                for (int i = 0; i < fcol.Count; i++)
                    sb.AppendFormat("{0}:{1},", fcol.AllKeys[i].ToString(), fcol[i].ToString());
                sb.Append("</Form collection>");
            }
            sb.Append("<br/>Form : ");
            if (Request.Form.Count > 0)
            {
                NameValueCollection form = Request.Form;
                sb.Append("<form>");
                for (int i = 0; i < form.Count; i++)
                    sb.AppendFormat("{0}:{1},", form.AllKeys[i].ToString(), form[i].ToString());
                sb.Append("</form>");
            }
            sb.Append("<br/>QueryString : ");
            if (Request.Form.Count > 0)
            {
                NameValueCollection form = Request.QueryString;
                sb.Append("<QueryString>");
                for (int i = 0; i < form.Count; i++)
                    sb.AppendFormat("{0}:{1},", form.AllKeys[i].ToString(), form[i].ToString());
                sb.Append("</QueryString>");
            }
            if (model != null)
            {
                sb.Append("<br/>Profile(ProfileModel m) : ");
                sb.AppendFormat("m.username = {0}, m.password = {1}", model.UserName, model.Password);
            }
            if (!ModelState.IsValid)
            {
                sb.Append("<br/>Model errors :");
                var errors = from key in ModelState
                             let errorList = ModelState[key.Key].Errors
                             where errorList.Any()
                             select new
                             {
                                 Item = key.Key,
                                 Value = key.Value,
                                 errorList
                             };

                foreach (var errorList in errors)
                {
                    sb.AppendFormat(@"<br/>MODEL ERROR: [{0}] value:'{1}' ", errorList.Item, errorList.Value);
                    foreach (var error in errorList.errorList)
                    {
                        sb.AppendFormat(" ERROR message: [{0}] exception : '{1}'", error.ErrorMessage, error.Exception);
                    }
                }
            }
            Response.Write(sb);
            //return new ContentResult();
            if (model != null)
                Log(new Exception(string.Format("model username : {0}, password : {1}, request[username] {2} , request[password] : {3}", model.UserName, model.Password, Request["UserName"], Request["Password"])));
            try
            {
                if (ModelState.IsValid)
                {
                    Log(new Exception(string.Format("ModelState {0}", ModelState.IsValid)));
                    Log(new Exception(string.Format("credentials {0},{1}", model.UserName, model.Password)));
                    if (MembershipService.ValidateUser(model.UserName, model.Password))
                    {
                        Log(new Exception(string.Format("MembershipService.ValidateUser {0},{1}", model.UserName, model.Password)));

                        FormsService.SignIn(model.UserName, false/* model.RememberMe*/);
                        Log(new Exception(string.Format("FormsService.SignIn {0},{1}", model.UserName, model.Password)));

                        //if (Url.IsLocalUrl(returnUrl))
                        //    return Redirect(returnUrl);
                        //else
                        return RedirectToAction("Index", "Home");
                    }
                    else
                        ModelState.AddModelError("", "The user name or password provided is incorrect.");
                }
            }
            catch (Exception ex)
            {
                Elmah.SqlErrorLog.GetDefault(System.Web.HttpContext.Current).Log(new Elmah.Error(ex, System.Web.HttpContext.Current));
            }
            // If we got this far, something failed, redisplay form
            return View("LogOn", model);
        }

and yes my razor page has validation summary

@Html.ValidationSummary(false, @LocalDealsResources.Strings.LogOnUnsuccessful)
@using (Html.BeginForm("LogIn", "Account"))
{
    <div>
        <fieldset>
            <legend>Account Information</legend>
            <div class="editor-label">
                @Html.LabelFor(m => m.UserName)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(m => m.UserName, new { style = " width:200px" })
                @Html.ValidationMessageFor(m => m.UserName)
            </div>
            <div class="editor-label">
                @Html.LabelFor(m => m.Password)
            </div>
            <div class="editor-field">
                @Html.PasswordFor(m => m.Password, new { style = " width:200px" })
                @Html.ValidationMessageFor(m => m.Password)
            </div>
            <p>
                <input type="submit" value="@LocalDealsResources.Strings.LogOn" />
            </p>
        </fieldset>
    </div>
}

give the form a try http://dealze.com.sapin.arvixe.com/Account/Logon

回答1:

In general, we would seperate our GET actions from our POST actions in MVC:

 [HttpGet]
 public ActionResult Index()
 {
      return View();
 }

 [HttpPost]
 public ActionResult Index(ViewModels.SubscriptionModel model)
 {
      if(!ModelState.IsValid)
      {
           return View(model);
      }
      else
      {
           // Code here to save to the database or something else
           return View("saved"); //Return a view that is designed to show a message
      }
 }

Notice on the post we check to see if the ModelState was valid, and if it wasn't we kick them back to the same view with the data they submitted? And if the model was valid, we do something and then return a differen view?

I would suggest that for debugging you also output a validation summary:

 <%: Html.ValidationSummary(false) %>

or for Razor

 @Html.ValidationSummary(false)


回答2:

I finally found what was causing this

In my application_beginrequest I log the info on a different thread, I guess the application continued running on that thread and could not find the Request in the context



回答3:

You need to use proper overloaded function of Html.Beginform method where in you mention that the Html Form is sending the request using HttpPost Form method. http://msdn.microsoft.com/en-us/library/dd460344.aspx