Software Gardening

.NET, web, community, architecture, practices

Ajax modal forms in ASP.Net MVC

I’m working on a project where the Bootstrap modal dialog is being used to popup data entry and other forms. I had it working using jQuery to handle the Ajax call to the Controller. It was a lot of work to gather the form data into the JSON packet, call the Controller and handle the return values, especially if the form did not pass validation.

address

I thought there had to be better way.  Here are the requirements I had:

  • The Bootstrap dialog must be modal
  • The form should not be loaded into the browser with the page. It will be read from the server when needed and then displayed.
  • The data must be sent via Ajax to the server.
  • If possible, validation should be performed client-side, before sending data to the server.
  • The form should stay open if Model Validation fails and validation messages should be displayed.

I did what any good developer does…I hit a search engine and found several articles that I had to piece together to make it all work. The process is quite simple:

  1. An Ajax request is sent from the browser.
  2. The server returns a partial view to the browser.
  3. Javascript code receives the form and it is placed as HTML into a specified div.
  4. The form is displayed.
  5. When the user clicks Save, the form data is sent to the Controller, just as any form data but with one exception…it’s sent as Ajax.
  6. The Controller method validates the data. If it passes validation, the data is saved, a success message is sent back to the server and displayed to the user, then the form is closed. If the data fails validation, it is returned to the form and the validation messages are displayed.

First, I had to setup the initial request. I put an empty div in the _Layout.cshtml file. This way, I can display dialogs from anywhere in the application.

<body class="dashboard" style="padding-top: 0px;">
        <div id="dialogPlaceholder"></div>
… remaining body code
</body>

Next, I placed an New Address button on the CompanyDetails form and set its click event to call the Javascript that loads the AddEdit form.

function openAddressDialog(id) {
    var data = {
        Id: id,
        CompanyId: $('#Id').val()
    };
    $.ajax({
        url: '/crm/customer/AddEditAddress/',
        contentType: 'application/html',
        data: data,
        success: function(content) {
            $('#dialogPlaceholder').html(content);
        },
        error: function(e) {}
    });        
}

The controller loads up the Model and returns the partial view. The form code is like any other form except that you make it an Ajax form.

@model Models.AddEditAddress

<div id="dialogResult"></div>

@using (Ajax.BeginForm("SaveAddressAjax", "shared", new AjaxOptions
{
    HttpMethod = "POST",
    InsertionMode = InsertionMode.Replace,
    OnSuccess = "updateAddressSuccess()",
    OnFailure = "dialogFailure()",
    OnBegin = "dialogBegin()",
    OnComplete = "dialogComplete()",
    UpdateTargetId = "dialogResult"
}))
{
… Rest of form code goes here.
} <script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script> <script src="~/Scripts/genericDialog.js"></script> <script> $(document).ready(function() { $('#addEditAddressDialog').modal(); });




function updateAddressSuccess() { $('#addEditAddressDialog').modal("hide"); } </script>

Look at the Ajax.BeginForm statement OnSuccess, OnFailure, OnBegin, OnComplete define Javascript functions that run when the specified event occurs. I created dummy methods that do nothing and placed them in genericDialog.js. Then, I can override each one, simply by providing a different Javascript function, for example updateAddressSuccess.

// genericDialog.js
function dialogSuccess() {}
function dialogFailure() {}
function dialogBegin() {}
function dialogComplete() {}

And that’s all there is to it. A simple dialog that is loaded on-demand. You can also use the same methodology to load ANY partial view on demand. For example, you may have a complex form with multiple tabs and only load the tab data when the user clicks on it. Finally, you can use this method to make your forms seem faster. Because you won’t have to load up everything in the form, it gets generated faster and less data is sent to the browser on initial load, making the application seem faster. Your users will thank you.

8 Comments

  1. And if your like me and use _ViewStart.cshtml for setting Layout, don’t forget to @{Layout=null;} in your partial view. I chased this one for hours.

  2. You can actually leave out @layout and the partial view will render correctly.

  3. Can you share your code ? Onsucess method doesnt seem to work for me!!

  4. Could you please share the code?!!!

  5. How can you modify this to Support mvc6 since Ajax helpers aren’t supported if i’m not mistaken

    • craigber

      April 19, 2016 at 4:36 pm

      ASP.NET Core is a very different animal. I’ll be posting about shortly after RC2 is released.

Leave a Reply

Your email address will not be published.

*

© 2017 Software Gardening

Theme by Anders NorenUp ↑