0

I have the following Action in my controller:

[HttpPost]
    public JsonResult RedirectToAspReportViewer(MvcReportPeriodSelectionViewModel periodFilter, MvcMultipleLocationSelectionViewModel locationFilter)
    {
        var jsonObject = new { HasErrors = false, strUrl = "/ASPReports/TreatmentOutcome.aspx" };

        if (ModelState.IsValid)
        {
            try
            {
                //some code
            }
            catch (ValidationException ex)
            {
                this.HandleValidationErrors(ex);
                jsonObject = new { HasErrors = true, strUrl = "/TreatmentOutcomeReport/Report/" };
            }
        }
        return Json(jsonObject);
    }

Then, in my Javascript, I have the following function, which get's called on my ajax post's OnSuccess function.

onSuccessCall: function (response) {
    if (response.HasErrors === true) {
        //window.location = window.location.href;
        location.reload();
    } else {
        window.open(response.strUrl);
    }
};

As you can see from above, if my reponse object has errors, I would like to stay on the current page, just refresh it so that my ModelState errors would still show.

The problem I am facing, is that when I call location.reload, my ModelState errors do not show on my page. I have a feeling it is because I am posting to the server again, and the ModelState gets cleared.

How can I avoid this?

UPDATE I cannot just add the validation error to the JsonResult, and in the client side, update the necessary DOM to display the errors. On all of my views, I have the following shared view which returns my errors: Below is the sample:

@model ModelStateDictionary

@{ 
    var cls = "alert-danger";
    var type = ViewBag.Type;
    if (type != null && type.ToString().ToLower() == "warning")
    {
        cls = "alert-warning";
    }

    var message = "Please attend to the following problems:";
    if (ViewBag.Message != null && ViewBag.Message.ToString().Trim() != "")
    {
        message = ViewBag.Message.ToString().Trim();
    }
}

@if (ViewData.ModelState.Keys.Any(k => ViewData.ModelState[k].Errors.Count()    > 0))
{
    <div class="alert @cls">
        <button class="close" data-dismiss="alert" aria-hidden="true">&times;   </button>
        @Html.ValidationSummary(false, message)
    </div>
}

This will get called at the top of all my views as follow:

<div id="valSummary">
    @Html.Partial("_ValidationSummaryDisplay", ViewData.ModelState)
</div>
monstertjie_za
  • 7,277
  • 8
  • 42
  • 73
  • 2
    `I have a feeling it is because I am posting to the server again` - no, that's because you are *not* posting to the server again. – GSerg Aug 12 '16 at 11:50
  • 2
    `location.reload` refreshes the page (it calls you GET method again and everything is lost) –  Aug 12 '16 at 11:51
  • 1
    Since your wanting to redirect to `/TreatmentOutcomeReport/Report` then there is no point of making an ajax call. Just do a normal submit and redirect in the POST method (or return the view if `ModelState` is invalid) –  Aug 12 '16 at 12:04
  • @StephenMuecke Everything worked as suggested, but the problem is, the report I am trying to load sits in an aspx page, that I want to open in a new tab. Since the target = "_blank" sits in the razor view, if the validation errors are shown, it is shown in the new tab opened, not the original tab. I tried this approach to handle the new tab opening with the report, or stay on current tab and display the errors, using jquery – monstertjie_za Aug 12 '16 at 12:07
  • Use client-side validation? Return a view that does or does not have a `` depending on the validation result? – GSerg Aug 12 '16 at 12:10
  • In that case, one option could be to add additional properties for the error message(s) and update the DOM to display the errors (and delete the `location.reload();`) –  Aug 12 '16 at 12:11
  • @GSerg The problem is, unless I am not understanding you, is that as soon as the form is submitted, the new Tab is opened already. With the above approach, I tried to ignore this scenario and first see if there is errors, if not, then open page in new tab, otherwise, stay on current. – monstertjie_za Aug 12 '16 at 12:12
  • Remove the `__blank` so that the form is rendered in the existing window. Have the `post` return a view. If there are errors, it will render the validation errors. If there are no errors, append the script block to the returned view that opens the new window. – GSerg Aug 12 '16 at 12:14
  • @StephenMuecke I will try your suggestion, was hoping it would not come to that. Is it possible to add the message to ModelState from client side? Currently I have a shared view that checks ModelState, and if found any errors, loops through them, and displays, so it is not as easy as just updating the DOM with the relevant message, unless I am misunderstanding you – monstertjie_za Aug 12 '16 at 12:16
  • Not sure what you mean by _shared view that checks ModelState_. What I meant was something like `if (response.HasErrors === true) { $(someElement).html(response.ErrorMessages); } else { window.open(response.strUrl); }` –  Aug 12 '16 at 12:19
  • @StephenMuecke Please check my updated question – monstertjie_za Aug 12 '16 at 12:24
  • Then you might need to return the 'ModelStateDictionary' partial view in the JsonResult, something like [this answer](http://stackoverflow.com/questions/4730777/mvc-return-partial-view-as-json) –  Aug 12 '16 at 12:29
  • Don't know why this did not come to mind, I am pretty sure this will work for me. If you would like to post as answer, I would gladly accept. – monstertjie_za Aug 12 '16 at 12:34

1 Answers1

-1

If you want your ModelState errors to show on the page, then you should

return View(yourViewModel);

When coding the view, be sure to include the helpers to show your validation:

@Html.ValidationMessage(m => m.PropertyName)

I am assuming your handle method puts the errors in the ModelState (as that is what it is for).

Fabio Milheiro
  • 8,100
  • 17
  • 57
  • 96
  • 1
    I know I can do return View, if it was possible for me to do that in this case, I would not be having this problem. How can I get the same behavior with jquery as what return VIew would have done? – monstertjie_za Aug 12 '16 at 11:59
  • Alright then you need to return your errors in the JON result and your java script will responsible for rendering it. Reloading the page will make you loose the validation information. – Fabio Milheiro Aug 12 '16 at 12:02