4

My Situation

I have a list of items(surveys) displayed on my home page. When I click the edit button for a particular item I have a modal pop up with the items details to edit. When the user clicks Save I submit the form via ajax. Depending on whether ModelState.IsValid == true I want to update the modal with validation information or close the modal and update the list of items with the new information.

This is how I am submitting the form:

    $('#editSurveyForm form').live('submit', function () {
        var f = $("#saveSurvey").parents("form");
        var action = f.attr("action");
        var serializedForm = f.serialize();
        $.ajax({
            type: "POST",
            url: action,
            dataType: "html",
            data: serializedForm,
            success: function (result) {
                //TODO - I need an indicator that validation was successful

                //If Validation Failed reload form with validation errors
                $('#editSurveyModal').html(result);

                //If Successful, reload Survey Partial View
                //$('#surveyBox').html(result);
            }
        });
        return false;
    });

My Questions

The only thing I can think to do is return JSON from my controller with a flag indicating the state of the ModelState.IsValid and the corresponding partial that I should show.

1) How would I do this?

2) Is there a better way?

Update

I found this: http://www.klopfenstein.net/lorenz.aspx/render-partial-view-to-string-in-asp-net-mvc

but it seems more likely that I am going about the whole thing incorrectly.

1
  • Can you just use an Ajax form - @Ajax.BeginForm("Action", "Controller") Commented Mar 16, 2011 at 14:48

4 Answers 4

1

One way to skip using JSON would be to look for certain elements within the returned HTML. If you're using any of the html helpers for validation messages (Html.ValidationSummary(), Html.ValidationMessageFor()) these will render elements with specific classes you can look for to decide the outcome. If not, you can make your own standards.

For example, if you're using the Html.ValidationSummary-method, it will render a list with the class validation-summary-errors. So you can set a variable like this and then handle the response accordingly.

var isValid = $(response).find(".validation-summary-errors").length == 0;

So in your situation:

success: function (result) {
    var isValid = $(result).find(".validation-summary-errors").length == 0;

    //If Successful, reload Survey Partial View
    if (isValid) {
         $('#surveyBox').html(result);
    }
    //If Validation Failed reload form with validation errors
    else {
        $('#editSurveyModal').html(result);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

This is probably what I'll end up doing. Seems hackish. I'll keep you posted.
1

You could return a flag that tell you if you got errors or not, and depending on this flag, a different set of data. If it's an error return something like:

{success: false, errors: ['Name invalid','email invalid']}

And if it's correct:

{success: true, Name:'new name',email: 'new email'}

and your Script

....
$.ajax({
        type: "POST",
        url: action,
        dataType: "html",
        data: serializedForm,
        success: function (result) {
            if(!result.success)
            {
                  //Show errors     
            }
            else
            {
                  // Update data
            }
        }
    });
.....

To show errors you can have a div in the modal popUp and then for each item on result.errors, append a div inside the error div.

If success is true, find the item you clicked, and update it with the date in your result.

Let me know if you don't know how to do this.

1 Comment

This is exactly what I am trying to avoid. I would like to leverage MVCs validation for my partial using the TextBoxFor(..) and attributes on the model.
1

Do it as it's suppose to be done

jQuery Ajax requests are able to handle success as well as error states. So the proper way is to actually return an error (not HTTP 200 state) from the server when you have validation errors. Don't return views unless you should display them. But even in that case they should be part of erroneous result to be displayed by different client side functionality (error handler function).

Read all details about this in my blog post. All code is provided there as well and everything is explained step by step so it's easy to understand.

It uses a custom exception class that gets thrown when there are any model state errors and a custom error action filter that uses this exception and returns an error to the client side. This makes it very easy to do Ajax request the proper way:

$.ajax({
    type: "POST",
    data: /* your data */,
    success: function(data, state, xhr) {
        // do wahetever required
    },
    error: function(xhr, state, err) {
        // do something about the error ie. inform the user about it
    }
});

This is much better than detecting errors in success state and having unnecessary branch in it. jQuery is supposed to be used this way and not with just the success handler.

A sidenote

I'm sorry for not seeing your question earlier because I suppose it would make you happier by the information it provides.

1 Comment

You can't take advantage of MVC's validation this way. Which is what my question was about. "How can I leverage MVC Validation without making a full postback?" This is to avoid having to handle the validation notification in javascript, which sucks.
0

My update partial view return index method. This method population my table, like update ajax jquery?

I like update only mu table in PartialView. This situation:

    <div class="container container-Top">
        <h4>Lista de categorias produtos</h4>
        <p>
            <hr />
            <br />
            @using (Html.BeginForm())
            {
                <div class="form-group">
                    <div class="col-lg-4">
                        @Html.TextBox("NomeCategoria", null, new { @class = "form-control" })
                    </div>
                    @Html.ActionLink("Pesquisar", null, null, new { @class = "btn btn-default", @id = "Pesquisar" })
                </div>
            }                       
            <br />
            <br />
            <br />
            <div id="DvDetalheCategoria" class="form-group">
                @Html.Partial("_DetalhesCategoria", Model)
            </div>
    </div>

My Jquery

    <script type="text/javascript">

            $(function () {
                $("#Pesquisar").click(function () {
                    var $btnPesquisar = $(this);
                    var idCategoria = $("#NomeCategoria").val();                
                    $.ajax({
                        url: '@Url.Action("_DetalhesCategoria", "VntCategoria")',
                        data: { pName: idCategoria },
                        type: 'POST',
                        success: function (data) {
                            $("#DvDetalheCategoria").html(data);                        
                        },
                        error: function (ex) {
                            alert('Falha ao carregar categorias' + item.Id);
                        }
                    });
                });
            });
        </script>

My controllers:

     // GET: /VntCategoria/
    public ActionResult Index()
    {
        return View(db.VntCategoriaProdutos.ToList());
    }

    [HttpPost]
    public ActionResult _DetalhesCategoria(string pName)
    {
        ListaCategorias = new List<VntCategoriaProdutos>();
        ListaCategorias = db.VntCategoriaProdutos.ToList().FindAll(f => f.DescricacaoCategoria == pName);
        return View(ListaCategorias);
    }

2 Comments

Is this meant to be an answer? In it's current state, I don't believe it is.
Sorry, but it's a question. My jquery always executes the index method. I would like you to only execute the method _DetalhesCategoria.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.