Ivan Stoyanov
Ivan Stoyanov

Reputation: 5482

Exception handling and status messages in MVC3 using JSON and jQuery

I am writing my code in MVC3 and C#. I want to send user friendly messages to the user when exceptions and custom exceptions occur. I am thinking of using JSON and jQuery popup boxes. Can you tell me how to do this? Is there a tutorial or article on this topic?

EDIT:

I want to create custom ActonFilter that extends IExceptionFilter. The custom filter catches exceptions (if they are thrown) and returns custom class ShowMessage(ex). The custom class returns JSON result containing the desired message. In the jQuery there is a parser that shows the popup box with the message (if there is an exception).

Upvotes: 1

Views: 686

Answers (1)

jhartzell
jhartzell

Reputation: 283

There are a number of ways to go about doing this if I seem to understand your question correctly.

My controller would look like this:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult ContactUs(DatabaseModelExtensions.ContactRequest model) // Pass          model of which I am submitting a form against to retrieve data inside this HTTPPost Controller
    {
        // Create database object to map extension class to it.
        ContactRequest NewEntry = new ContactRequest();

        if (ModelState.IsValid)
        {
            // Map database object to the model passed and then insert.
            NewEntry.Name = model.Name;
            NewEntry.Email = model.Email;
            NewEntry.Message = model.Message;
            NewEntry.Timestamp = System.DateTime.Now;

            // Insert new entry into database for historical tracking
            NewEntry.Insert();

            // Clear modelstate (clearing form fields)
            // ModelState.Clear(); -- Does not work with an Ajax call - requires postback.

            // Email user about their contact request and also send admins a summary of the contact request.
            // Create new UserMailer Object so that we can invoke this class and work with it's functions/properties.
            var Mailer = new UserMailer();

            // Instantiated the 'msg' variable that will allow for us to invoke Mailer.ContactSubmission(), this function passes a series of parameters so that we can reference them inside
            // our UserMailer.cs class which then gets passed to a mail template called ContactSubmission.cshtml under the Views -> UserMailer folder
            var msg = Mailer.ContactSubmission(firstName: model.Name, email: model.Email, telephone: model.Telephone);

            // Same as above except we will be sending out the management notification.
            var msg1 = Mailer.AdminContactSubmission(firstName: model.Name, email: model.Email, datetime: System.DateTime.Now, message: model.Message, telephone: model.Telephone);

            // Invoke the .Send() extended function that will actually execute everything to send an SMTP mail Request.
            msg1.Send();
            msg.Send();


            // Return our content back to the page asynchronously also create a quick snippet of js to slide the message up after a few seconds.               
            return Content(new MvcHtmlString(@"
                                    <div id='sendmessage'>
                                        Your message has been sent, Thank you!
                                    </div>
                                    <script type='text/javascript'>
                                       setTimeout(function () { jQuery('#results').slideUp('fast') }, 3000);
                                    </script>").ToString());
        }
            // Return our Error back to the page asynchronously.
        return Content(new MvcHtmlString(@"
                                    <div id='errormessage'>
                                        An error has occured, please try again in a few moments!
                                    </div>
                                    <script type='text/javascript'>
                                       setTimeout(function () { jQuery('#results').slideUp('fast') }, 3000);
                                    </script>").ToString());
    }

My view would then look something like:

<div id="results">Content would be returned in place of this div.</div>
@using (Ajax.BeginForm("ContactUs", "Home",
        new AjaxOptions
        {
            LoadingElementId = "loading",
            OnBegin = "DisableForm('contactform')",
            UpdateTargetId = "results",
            OnSuccess = "resetForm('contactform'); removeLoading()"
        }, new { @id = "contactform" }))
    {       
        @Html.ValidationSummary(true)           
        <div id="results">

        </div>
        <ul class="cform">
            <li><label for="name">Name:</label>             
            @Html.TextBoxFor(Model => Model.Name, new { @name = "name", @id = "name", @class = "fancyinput reginput" })
            @Html.ValidationMessageFor(Model => Model.Name)
            </li>
            <li><label for="email">E-mail:</label>
            @Html.TextBoxFor(Model => Model.Email, new { @name = "email", @id = "email", @class = "fancyinput reginput" })
            @Html.ValidationMessageFor(Model => Model.Email)
            </li>
             <li><label for="telephone">Telephone:</label>
            @Html.TextBoxFor(Model => Model.Telephone, new { @name = "telephone", @id = "telephone", @class = "fancyinput reginput" })
            @Html.ValidationMessageFor(Model => Model.Telephone)
            </li>
            <li><label for="message">Message:</label>
            @Html.TextAreaFor(Model => Model.Message, new { @name = "message", @id = "message", @class = "fancyinputarea", @rows = "10", @cols = "62" })
            @Html.ValidationMessageFor(Model => Model.Message)
            </li>
            <li><input type="submit" value="Submit" class="btn" name="submit"/><img id="loading" style="display: none;" src="../../Content/img/loading27.gif" alt="Loading..." /></li>
        </ul>
    }

This is a simple example of a contact page with full functionality for ajax and warning the user of when something is happening via a loading div with a css background of an animated gif and also letting them know their outcome success/fail.

You can also achieve a similar effect and more by using an ActionResult, calling that and returning Content

 public ActionResult SubmitForm(int id)
 {
      return Content(new MvcHtmlString("<div>test test</div>").ToString());
 }

 and the jQuery AJAX side of things would be;

 $.ajax({
   type: 'POST',
   url: @Url.Action("SubmitForm","VotingController"),
   data: { id : @Model.UserId },
   success: success, // Javascript function to call back on success.
   dataType: dataType // data type expected back from the server
 });

This later half - just consider it as pseudo code as I just wrote it up on the fly but should work with small tweaks.

Hopefully this is of help to you and I don't get laughed at for doing something incorrectly, however, if I did and someone can show me a better way I would love to better myself as well :)

Upvotes: 1

Related Questions