tobbbe
2/18/2015 - 12:50 PM

MVC Unobtrusive ajax form

MVC Unobtrusive ajax form


1. add these after jquery (jquery version newer than 1.8)
	<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
	<script src="http://ajax.aspnetcdn.com/ajax/mvc/4.0/jquery.validate.unobtrusive.min.js"></script>
	<script src="~/scripts/jquery.unobtrusive-ajax.min.js"></script> <--- get this from nuget pack
	
(instead of using cdn, get them as nuget packs: "jquery validation", "Microsoft jquery unobtrusive ajax", "Microsoft jquery unobtrusive validation")

2.a add these in <appSettings> in web.config
	<add key="ClientValidationEnabled" value="true" />
    	<add key="UnobtrusiveJavaScriptEnabled" value="true" />

2.b or add this in the view of the form (like in the example, point 5 futher down)
	HtmlHelper.UnobtrusiveJavaScriptEnabled = true;
    	HtmlHelper.ClientValidationEnabled = true;

3. Add a model and a controller for the form, ex:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using Umbraco.Web.Mvc;
using System.Net.Mail;
using System.Web.Mvc;

namespace Fasty.ContactForms.ContactFormForProducts
{
    public class FormSurfaceController : SurfaceController
    {
        [HttpPost]
        public ActionResult Sendmail(Fasty.ContactForms.ContactFormForProducts.Model model)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    MailAddress Receiver = new MailAddress("example@mail.com");
                    MailAddress Sender = new MailAddress(" Kontaktformulär <no-reply@email.com>");
                    MailMessage email = new MailMessage(Sender, Receiver);

                    email.ReplyToList.Add(model.Email);
                    email.Subject = model.Name;
                    email.Body =
                    "Namn: " + model.Name + Environment.NewLine +
                    "Epost: " + model.Email + Environment.NewLine +
                    "Meddelande: " + Environment.NewLine + model.Message;

                    //SETTING SMTP SERVER VARIABLES
                    SmtpClient Server = new SmtpClient();
                    Server.Host = "smtp.email.com";

                    //SENDING MESSAGE
                    Server.Send(email);

                    ModelState.Clear();
                    return Content("email successfully sent");
                }
                catch (Exception ex)
                {
                    return Content("error sending email");
                    //throw;
                }

            }

            ModelState.AddModelError("OnFailure", "asd");
            return Content("could not send mail, model not valid");
        }
    }

    public class Model
    {
        [Required(ErrorMessage = "Namn saknas")]
        [DisplayName("Name")]
        public string Name { get; set; }
        
        [Required]
        [EmailAddress(ErrorMessage = "Invalid Email Address")]
        [DisplayName("Email")]
        public string Email { get; set; }

        [Required]
        [DisplayName("Message")]
        public string Message { get; set; }
    }

}

4. If you've put the form in a partialview, add it like this: @Html.Partial("_ContactFormForProducts", new Fasty.ContactForms.ContactFormForProducts.Model())

5. And then finally add the form:

@model Fasty.ContactForms.ContactFormForProducts.Model

@{
    HtmlHelper.UnobtrusiveJavaScriptEnabled = true;
    HtmlHelper.ClientValidationEnabled = true;
}

<section id="product-contactForm">

    @using (Ajax.BeginForm("Sendmail", "FormSurface",
        new AjaxOptions
        {
            HttpMethod = "POST",
            OnFailure = "Fasty.productFormFail",
            OnSuccess = "Fasty.productFormSuccess"
        }
        ))
    {
        @Html.TextBoxFor(x => x.Name, new { @placeholder = "Namn", @class = "left", autocomplete = "off" })
        @*@Html.ValidationMessageFor(x => x.Name)*@

        @Html.TextBoxFor(x => x.Email, new { @placeholder = "Mailadress", @class = "left", autocomplete = "off" })
        @*@Html.ValidationMessageFor(x => x.Email)*@

        @Html.TextAreaFor(x => x.Message, new { @placeholder = "Meddelande", @rows = "7", @class = "left", autocomplete = "off" })
        @*@Html.ValidationMessageFor(x => x.Message)*@

        <input type="submit" value="Skicka" />
        @*<span id="mailSuccessMessage" class="hide">Tack för ditt mail!</span>
        <span id="mailErrorMessage" class="hide">Något gick fel. Vänligen försök igen</span>*@

        @Html.ValidationSummary(true)
    }

</section>

6. add js error handling

window.Fasty = {
    productFormFail: function (e) {
        console.log(e);
        $('#mailErrorMessage').removeClass('hide');
    },
    productFormSuccess: function () {
        var $mailsuccessmessage = $('#mailSuccessMessage');
        var $sendButton = $('#sendmailButton').addClass('success');

        $mailsuccessmessage.removeClass('hide');

        var $form = $('#product-contactForm').find('form');

        // reset jQuery Validate's internals
        $form.validate().resetForm();

        //reset unobtrusive validation summary, if it exists
        $form.find("[data-valmsg-summary=true]")
            .removeClass("validation-summary-errors")
            .addClass("validation-summary-valid")
            .find("ul").empty();

        //reset unobtrusive field level, if it exists
        $form.find("[data-valmsg-replace]")
            .removeClass("field-validation-error")
            .addClass("field-validation-valid")
            .empty();

        // reset form
        $form[0].reset();

        setTimeout(function () {
            $mailsuccessmessage.addClass('hide');
            $sendButton.removeClass('success');
        }, 4000);
    }
};