binary binary - 2 months ago 30
Ajax Question

Returning Partialview & JSON from MVC 5 Controller

In an MVC5 project, I open a modal dialog and in case there is an exception, I want to open this dialog and display a message on a div in this dialog. As far as I see, I should follow the approach as rendering partialview into a string, but most of the examples does not work in MVC5 as on Return Partial View and JSON from ASP.NET MVC Action. Is there any similar or better approach working for MVC5?

Answer

You can do the following

Solution 1 ( using partial views)

[HttpPost]
public ActionResult YourAction(YourModel model)
{
    if(model!=null && ModelState.IsValid)
    {
          // do your staff here
          Response.StatusCode = 200; // OK
          return PartialView("ActionCompleted");
    }
    else
    {
          Response.StatusCode = 400; // bad request
          // ModelState.ToErrors() : is an extension method that convert 
          // the model state errors  to dictionary
          return PartialView("_Error",ModelState.ToErrors());
    }
}

Your partial view should look like:

<div id="detailId">
     <!-- Your partial details goes here -->
     ....
         <button type="submit" form="" value="Submit">Submit</button>

</div>

your script

<script>
    $(document).ready(function(){
         $('#formId').off('submit').on('submit', function(e){
               e.preventDefault();
               e.stopPropagation();

               var form = $('#formId');
               $.ajax({
                   url: form.attr('action'),
                   data: form.serialize(),
                   method: 'post',
                   success : function(result){
                        $('#detailId').replaceWith(result);
                        // another option you can close the modal and refresh your data.
                   },
                   error: function(data, status, err){
                       if(data.status == 400){
                           $('#detailId').replaceWith(data.responseText);
                       }
                   }
               });

         });
    });
</script>

Solution 2 ( using Json)

in your action

[HttpPost]
public ActionResult YourAction(YourModel model)
{
    if(model!=null && ModelState.IsValid)
    {
          // do your staff here              
          return Json(new {status = 200, 
                           //...any data goes here... for example url to redirect
                        url=Url.Content("YourRedirectAction","Controller")},
    }
    else
    {              
          return Json( new {status= 400,errors = ModelState.ToErrors()});
    }
}

and your script should look like

<script>
    $(document).ready(function(){
         $('#formId').off('submit').on('submit', function(e){
               e.preventDefault();
               e.stopPropagation();

               var form = $('#formId');
               $.ajax({
                   url: form.attr('action'),
                   data: form.serialize(),
                   method: 'post',
                   success : function(result){
                        if(result.status==200) { // OK
                            // you might load another action or to redirect
                            // this conditions can be passed by the Json object
                        }
                        else{ // 400 bad request
                            // you can use the following toastr based on your comment
                            // http://codeseven.github.io/toastr/demo.html
                             var ul = $('<ul>')
                             for(var error in result.errors)
                             {
                                 ul.append('<li><b>' + error.Key + '</b>:' + error.Value + '</li>;
                             }
                             toastr["warning"](ul[0].outerHTML);
                        }
                   }
               });

         });
    });
</script>

Finally, if you want the extension ModelState.ToErrors()

public static IEnumerable ToErrors(this ModelStateDictionary modelState)
{
     if (!modelState.IsValid)
     {
         return modelState.ToDictionary(kvp => kvp.Key,
                 kvp => kvp.Value.Errors
                           .Select(e => e.ErrorMessage).First())
                           .Where(m => m.Value.Count() > 0);
     }
     return null;
}

hope this will help you

Comments