Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Minimalistic Example of Sending and Receiving Data Between the Client (View) and Server (Controller) via AJAX in an ASP.NET MVC App

0.00/5 (No votes)
25 Apr 2016 1  
Simplest possible step-by-step instructions on how to set up an ASP.NET MVC app to use AJAX from the client to call a Controller method, sending data from the client (jquery code on a View) to the server (C# code on a Controller), and then response data back from the server to the client.

Most Valuable Code (Isn't that what MVC stands for?)

Caveat: I am not a jQuery or ASP.NET MVC guru, or even an expert. What I show you in this tip is the result of implementing the answers from several different people to several different questions that I pos[t]ed on StackOverflow.

I won't go into the theory behind or the raison d'etre of MVC; I will just show you what you need to do to send some data from a couple of html elements on a page to a controller, and then some other data back again, from the controller to the page.

These are the basic steps (this assumes you already have a page with some HTML elements on it) you can follow (and tweak, as necessary):

Create a Model

A model is just a regular old C# class (right-click your Models folder and select Add > Class), and can be as simple as this:

public class UnitReportPairModel
{
    public List<string> UnitReportPairEmailVals { get; set; }
}

So this model defines a single member, a generic list of string. You should create it in your project's Models folder (I named it UnitReportPairModel.cs).

Create a Controller

The Controller is a little more specialized, inheriting Controller, but can be rather short/simple/sweet:

public class UnitReportPairController : Controller
{
    public JsonResult GetUnitReportPairEmailAddresses(string unit, string report)
    {
        UnitReportPairModel model = new UnitReportPairModel();
        try
        {
            int rptId = GetReportIDForName(report);

            DataTable UnitReportPairEmailValsDT = new DataTable();
            string qry = string.Format(SQL.UnitReportPairEmailQuery, unit, rptId);
            UnitReportPairEmailValsDT = SQL.ExecuteSQLReturnDataTable(
                qry,
                CommandType.Text,
                null
                );

            List<string> emailAddresses = UnitReportPairEmailValsDT
                     .AsEnumerable()
                     .Select(row => row.Field<string>("EmailAddr"))
                     .ToList();

            model.UnitReportPairEmailVals = emailAddresses;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        return Json(model, JsonRequestBehavior.AllowGet);
    }

    private int GetReportIDForName(string rpt)
    {
        string qry = string.Format(SQL.RptIDForRptNameQuery, rpt);
        return SQL.GetIntValForQuery(qry);
    }
}</string>

You should create this controller file (I named it UnitReportPairController.cs) in your project's Controllers folder. You can create one of these by right-clicking your project's Controller folder and selecting Add > Controller... > MVC 5 Controller - Empty. replace the default ActionResult Index() that returns View() with your custom code.

This controller is where the model's member[s] is/are inflated/populated. How you do that (with calls to a database or whatever) are, of course, completely up to you. In the case shown above, a call to a SQL Server database is made, then the results are saved to a generic list of string, which are assigned to the Model's member, and returned as json. But to who? That's where the VIEW part comes in. Note first, though, that your Controller can have standalone/utility methods such as GetReportIDForName().

Create a View

As already mentioned, it is assumed that you already have some html on a page. In the scenario I'm showing, I created a select element and a bunch of checkboxes, like this (the CSS classes are, for the most part, bootstrap), which I added to the existing Index.cshtml file in the Views\Home folder:

@* row 1: Create select element with "Unit" options *@
<div class="row">
    <div class="col-md-12">
        <label class="sectiontext">Select a Unit</label>
        <select class="form-control, dropdown" 
        id="unitsselect" name="unitsselect">
            <option disabled selected value="-1">Please choose a Unit</option>
            @foreach (var field in units)
            {
                <option id="selItem_@(field.unit)" 
                value="@field.unit">@field.unit</option>
            }
        </select>
    </div>
</div>

@* row 2: Create Report checkboxes *@
<div class="row">
    <div class="col-md-12" id="unitsCheckboxDiv">
        <div class="containerforplatypus">
            <label class="sectiontext">Select Report[s]</label>
            @foreach (var rpt in reports)
            {
                @* convert id to lowercase and no spaces *@
                var morphedRptName = @rpt.report.Replace(" ", string.Empty).ToLower();
                <input class="ckbx leftmargin8" 
                id="ckbx_@(morphedRptName)" type="checkbox" 
value="@rpt.report" />@rpt.report
            }
        </div>
    </div>
</div>

Wait, There's More

This is an additional piece of HTML that figures into the "receiving-data-back-in-the-AJAX-callback" part of this tip:

@* row 3: Email recipients input/text elements  *@
<div class="row">
    <div class="col-md-12">
        <div class="containerforplatypus">
            <h4 class="h4, sectiontext">Specify Recipients</h4>
            <label class="margin4horizontal">Email 1</label>
            <input type="text" name="email1" id="email1" />
            <label class="margin4horizontal">Email 2</label>
            <input type="text" name="email2" id="email2" />
            <label class="margin4horizontal">Email 3</label>
            <input type="text" name="email3" id="email3" />
            <button class="btn btn-primary" name="addlEmails" 
            id="addlEmails">Add Another Email</button>
        </div>
    </div>
</div>

Now the jQuery Part of It

I reckon it is considered better practice to break jquery code into separate files, storing them in a Scripts folder, but I just added a Script section at the bottom of the page, which you can do like so:

@section Scripts
{
    <script type="text/javascript">
        $(document).ready(function () {
		        // add "ready function" code
        });

        // Add other code
    </script>
};

I have a moderate amount of code in the Script section, but to avoid confusing the issue and to keep this tip as simple and focused as possible, I am just going to show the parts that pertain specifically to the interchange of data between the page (client/jquery code) and the server (controller/C# code):

$(".ckbx").change(function () {
    var unitval = $('#unitsselect').val();
    var rptval = $(this).val();

    var model = JSON.stringify({ unit: unitval, report: rptval });
    $.ajax({
        type: 'GET',
        url: '@Url.Action
        ("GetUnitReportPairEmailAddresses", "UnitReportPair")',
        data: { unit: unitval, report: rptval },
        contentType: 'application/json',
        cache: false,
        success: function (returneddata) {
            populateemails(returneddata);
        },
        error: function () {
            alert('hey, boo-boo!');
        }
    });
}); // $(".ckbx").change(function ()

For the AJAX call above to reach your control, the Control needs to be named UnitReportPairController (the first argument is the name of the method, the second is the name of the Controller sans the "controller" appendage).

So this AJAX call is sending two string values, such as "RED ROBIN" and "PRODUCE USAGE" to the Controller method. What it gets back from that method (a jsonified generic list of string, or an array of string) is dealt with in the success/error dual callback. If the call returns successfully, and the "success" block is reached, it calls the method populateemails, passing the returned data along to it. This method is:

function populateemails(trampdata) {
    // first, clear them all
    $("#email1").val('');
    $("#email2").val('');
    $("#email3").val('');
    // Now set those for which there are values
    if (trampdata.UnitReportPairEmailVals.length > 0) {
      $("#email1").val(trampdata.UnitReportPairEmailVals[0]);
    }
    if (trampdata.UnitReportPairEmailVals.length > 1) {
      $("#email2").val(trampdata.UnitReportPairEmailVals[1]);
    }
    if (trampdata.UnitReportPairEmailVals.length > 2) {
      $("#email3").val(trampdata.UnitReportPairEmailVals[2]);
    }
}

Note: This jquery is doubtless rude, crude, and unrefined; feel free to refactor and elegantize it.

Riding Off into the Sunset

And there you have it - selecting a unit and a report invokes the AJAX call, which gets the appropriate email addresses for that unit/report pair, and populates the input text emails with those values. If this tip saves you time, be sure to use that time doing something useful, such as coming up with an antidote for Duckbill Platypus venom (they have a poison toe, don't ya know).

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here