We use cookies to provide you with a great user experience, analyze traffic and serve targeted promotions.   Learn More   Accept
Card image cap

POSTing an ASP.NET Core MVC Form using jQuery, Bootstrap and TagHelpers

ASP.NET Core  • Posted one month ago

Let's talk about how we can POST a simple form data onto an ASP.NET Core MVC back-end endpoint via jQuery. We shall use BootStrap 4 for structuring the form elements easily and on top we shall use the aspnetcore tag helpers which provide better bindings for the back-end controller attributes onto the front-end forms.

Let's take our example of a Reader be added onto the reader store, for this we would need to create a sample Model which shall carry the data between the front-end View and the back-end Controller components. Let the model be as below:

The Model:


namespace ReadersMvcApp.Models
{
    public class ReaderModel
    {
	      [Required]
        [StringLength(200)]
        public string Name { get; set; }

        [Required]
        [EmailAddress]
        [StringLength(250)]
        public string EmailAddress { get; set; }

        public bool IsSuccess { get; set; }

        public string ReaderId { get; set; }
    }
}

While the Name and EmailAddress fields are input attributes to the controller from the View, the result of the operation is decided by the IsSuccess and ReaderId attributes which are set once the Reader is added onto the ReaderStore.

Next, we shall develop a form which accommodates these attributes along with their validation responses for any erroneous input.

The View:


@model ReadersMvcApp.Models.ReaderModel

<div class="container-fluid">
    <form asp-controller="Readers" asp-action="New" class="form">
        <div class="form-group">
            <label asp-for="Name"></label>
            <input asp-for="Name" class="form-control" />
            <span class="text-danger" asp-validation-for="Name"></span>
        </div>
        <div class="form-group">
            <label asp-for="EmailAddress"></label>
            <input asp-for="EmailAddress" type="email" class="form-control" />
            <span class="text-danger" asp-validation-for="EmailAddress"></span>
        </div>
        <button class="btn btn-primary" type="submit">Submit</button>
    </form>
</div>

Observe that we have used asp-* tags to define the endpoint, action and for scaffolding the model attributes which are to be passed onto the specified endpoints. These are called as taghelpers which come along with the aspnetcore MVC template and which help in making things easier for us while POSTing data to the controller from the form. This is because in general when we want to POST form to a controller using a model, we would need to ensure that the property names in the model match with the "name" and "id" properties of the HTML fields, otherwise these values shall not be captured and assigned to the model object. These tag helpers solve this problem by creating a scaffold between the HTML inputs we use and the intended Model property to be binded. And they take care of the assignment part themselves.

Same is the case with the asp-controller and asp-action taghelpers, together they form the "action" HTML attribute of the form tag. This ensures that the correct action is attached to the form, no matter what route the controller or the action is actually mapped to.

Now that we are done with the View, let's add the necessary jQuery logic to post this form. Now this is done in two ways:

Let's say we don't write any frontend handler ourselves and click on submit, still the data is submitted to the controller with the model data, but we can't add any customization to this (for example adding spinners, loading popups for failure handling and such) because the default jQuery files which come bundled within the MVC template handle this HTTP request for us and they can't be changed. For this, we override the behavior by adding our own jQuery submit event handler and then POSTing the form ourselves. This is done as below:

The Script:

$(document).ready(function () {

$("form")
    .submit(function (event) {
        debugger;
        event.preventDefault();
        
        // fetch the form object
        $f = $(event.currentTarget);

        // check if form is valid
        if ($f.valid()) {
            $("div.loader").show();
            // fetch the action and method
            var url = $f.attr("action");
            var method = $f.attr("method");

            if (method.toUpperCase() === "POST") {

                // prepare the FORM data to POST
                var data = new FormData(this);

                // ajax POST
                $.ajax({
                    url: url,
                    method: "POST",
                    data: data,
                    processData: false,
                    contentType: false,
                    success: handleResponse,
                    error: handleError,
                    complete: function (jqXHR, status) {
                        console.log(jqXHR);
                        console.log(status);
                        $f.trigger('reset');
                    }
                });
            }
        }
    });

    function handleResponse(res) {
        debugger;
        $("div.loader").hide();

        // check if isSuccess from Response
        // is False or Not set
        if (!res.isSuccess) {
            debugger;
            // handle unsuccessful scenario
        } else {
            // handle successful scenario
        }
    }

    function handleError(err) {
        $("div.loader").hide();
        if (xhr.responseText)
            showErrorMessage(xhr.responseText);
        else
            showErrorMessage("Some unknown error has occured. Please try again later.");
    }

    function showErrorMessage(message) {
        // show a popup logic or an alert logic
    }

});

Here we use the "submit" event handler on the "form" element and do the needful ourselves, in addition we can add customization like adding a spinner (<div.loader> tag) for all the time the form is being processed, or handle the success or failure cases better. In any case, this provides us with better control over the form than not using this. This entire logic resides under site.js under the wwwroot folder for better caching and bundling.

And finally the controller logic is as below:

The Controller:


namespace ReadersMvcApp.Controllers
{
    public class ReadersController : Controller
    {
        private readonly IReaderRepo _repo;
        private readonly IHostEnvironment _env;

        // default constructor
        // where any instance level
        // assignments happen
        public ReadersController(IReaderRepo repo, IHostEnvironment environment)
        {
            _repo = repo;
            _env = environment;
        }

        // default GET Endpoint which
        // renders the View for us
        // from ~/Views/Readers/New.cshtml
        public IActionResult New()
        {
            return View();
        }

        // default POST Endpoint which
        // receives data from the Form submit
        // at ~/Views/Readers/New.cshtml
        // and returns the response to
        // the same View
        [HttpPost]
        public async _Task<IActionResult>_ New([FromBody]ReaderModel model)
        {
            // magic happens here
            // check if model is not empty
            if (model != null)
            {
                // create new entity
                var reader = new Reader();

                // add attributes
                reader.Name = model.Name;
                reader.EmailAddress = model.EmailAddress;

                .. And the logic happens
	   } 
	}
}

Observe that we use [FromBody] attribute for the model to be captured, since we are using $.ajax which pushes data inthe form of content "application/json" we would require this attribute to state that the request content is coming in the body section, to be processed by the controller. And once the model is received, the magic happens within the controller.

In this way, we can implement a simple POST form and submit it to an ASP.NET Core MVC Controller using jQuery and TagHelpers complemented by the BootStrap form classes.

Published one month ago

Sponsored Links