B. Clay Shannon B. Clay Shannon - 6 months ago 14x
Javascript Question

How can I respond to events on a page in an ASP.NET MVC app that need to access data within the View?

In my ASP.NET MVC project, I need to dynamically manipulate some html elements when the user makes a couple of selections. I assume this needs to be done in code-behind C# (as opposed to in jquery), because how I respond is using data that is retrieved from a SQL Server database and is part of the View (I don't think jQuery would/could know about this MVC/.NET-specific data).

Specifically, when a user clicks a checkbox on the page, provided a selection has been made from an html-select element, my code needs to spring into action to populate other elements on the page.

The View (.cshtml) is getting the data in a Razor code block like so:

@model WebAppRptScheduler.Models.HomeModel
@using System.Data
DataTable dtUnitReportPairEmailVals = Model.UnitReportPairEmailVals DataTable;
var unitRptPairEmailVals = from x in dtUnitReportPairEmailVals.AsEnumerable()
select new
emailAddr = x.Field<string>("EmailAddr")

This data comes from the Controller:

DataTable UnitReportPairEmailValsDT = new DataTable();
UnitReportPairEmailValsDT = SQL.ExecuteSQLReturnDataTable(SQL.UnitReportPairEmailQuery, CommandType.Text, null);
model.UnitReportPairEmailVals = UnitReportPairEmailValsDT;

Does this (event handling) code belong in the Controller? If so, how is the method declared/decorated so that there is a connection between it and the html elements whose events it needs to monitor?

This is what needs to happen:

  1. User selects an option from an html select

  2. User clicks a checkbox

  3. The code determines that both an option has been selected, and a checkbox checked; it then uses the data to populate other controls, something like this:

    @if (unitRptPairEmailVals.Count > 0)
    email1.Text = unitRptPairEmailVals[0];
    @if (unitRptPairEmailVals.Count > 1)
    email2.Text = unitRptPairEmailVals[1];
    @if (unitRptPairEmailVals.Count > 2)
    email3.Text = unitRptPairEmailVals[2];

The above would populate the text/value of these html inputs:

<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" />

BTW, if I'm barking up the wrong tree, or am even in the wrong forest altogether, please let me know what the preferred approach is.


Update: I was answering on mobile last night, and here is a clearer edit and some sample code...

Asp.net MVC has controllers, which contain actions. When you navigation to a URL (HTTP GET), ASP.net translates this via routes into a specific controller action to invoke, then the result of that action is sent back to the browser as plain HTML.

Also when you submit a form (HTTP POST) to specific URL it translates to invoking a controller action via routes. and a ModelBinder will read the body of that HTTP POST and converts it into your Model class. Unlike the classic web forms that used ViewState to track page controls, state, and events.

What you want to achieve can be done in 2 different ways...

  1. Using JavaScript and JQuery. You can issue an Ajax request (GET, POST, etc) to a URL that exists in your ASP.net MVC routes table to execute an action and the results will be returned back to your JavaScript without navigating to another page.

  2. Posting an HTML Form back to the server will allow ASP.net MVC to read the new/changed values in your HTML controls and pass those new values to the controller action, which in turn can render the same view again with the new values and behaviour.