简体   繁体   中英

Call form OnFailure handler from controller, ASP.NET MVC

I'd so appreciate if someone could advise.

I have an Ajax form:

  @using (Ajax.BeginForm("Edit", null, new AjaxOptions() { 
                                       UpdateTargetId = updateRegion, 
                                       InsertionMode = InsertionMode.Replace, 
                                       OnFailure = "formFailure" }))
    {}

Its UpdateTargetId differs based on the current User role:

@{
   if (curUser.IsInputer)
    {
        updateRegion = "content";
    }
    else if (curUser.IsAuthorizer)
    {
        updateRegion = "mainPane";
    }
}

If the modelstate is invalid I'd like to return view in mainPane always:

<script>
function formFailure(result)
{
    $("#mainPane").html(result.responseText);        
}
</script>

However onFailure is not called when ModelState is invalid. For this, I set error code in controller:

public ActionResult Edit(ContractModel entity)
 {
    if(ModelState.IsValid)
    { 
       if(curUser.isInputer) { return RedirectToAction("SomeAction");}
       if(curUser.Authorizer) { return RedirectToAction("OtherAction");}
    }

     Response.StatusCode = 500;//internal server error to fire OnFailure of form
     return PartialView(entity);
 }

Then I get the desired result, ie I see the model with its errors in mainPane div and internal server error in browser console. However, it works this way when I run the application locally, when I publish and run it on the server, I see the error 500 Internal server error , instead of the partial view. Is there any workaround?

EDIT: As an option I tried to check Model for errors in form OnSuccess handler:

    var isValid = @Html.Raw(Json.Encode(ViewData.ModelState.IsValid));

        if (!isValid) {

            $("#mainPane").html(result.responseText);    
        }

But I still get the view in "content" div. Why is this happening?

Here is an option:

Dont use a 500 status error. That is for reporting something going very wrong with your application. That is not what has happened here, you simply have a form validation error.

Update your server side code to this:

public ActionResult Edit(ContractModel entity)
 {
    if(ModelState.IsValid)
    { 
       if(curUser.isInputer) { return RedirectToAction("SomeAction");}
       if(curUser.Authorizer) { return RedirectToAction("OtherAction");}
    }

    if(!ModelState.IsValid)
    {
        entity.FormError = true; // you will need to add this attribute to your model
    }

    return PartialView(entity);
}

Then in your partial view, put something like this:

if(Model.FormError)
{
    @Html.HiddenFor(m => m.FormError)
}

Change your form to handle the OnComplete event instead of OnFailure event. This is because your ajax post is not failing. Its returning successfully and reporting there was a validation error with the forms input:

@using (Ajax.BeginForm("Edit", null, new AjaxOptions() { OnSuccess = "handleFormResponse" }))
  {}

Change your handler script to something like this. This will check the response to see if contains a form error

  <script>
  function handleFormResponse(result)
  {
        $(result).find("#FormError").length > 0)
        {
            $("#mainPane").html(result);  
        }
        else
        {
            $("#@updateRegion").html(result);
        }

  }
  </script>

This is likely happening because the server is interpreting the 500 as an unhanded error and returning the default 500 error since your customErrors setting in the web config likely gets flipped to false when you publish the application in release mode.

Edit: Removed mention of using another status code as it caused more confusion and does not solve the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM