How to make update panel in ASP.NET MVC - asp.net-mvc

How do I make an update panel in the ASP.NET Model-View-Contoller (MVC) framework?

You could use a partial view in ASP.NET MVC to get similar behavior. The partial view can still build the HTML on the server, and you just need to plug the HTML into the proper location (in fact, the MVC Ajax helpers can set this up for you if you are willing to include the MSFT Ajax libraries).
In the main view you could use the Ajax.Begin form to setup the asynch request.
<% using (Ajax.BeginForm("Index", "Movie",
new AjaxOptions {
OnFailure="searchFailed",
HttpMethod="GET",
UpdateTargetId="movieTable",
}))
{ %>
<input id="searchBox" type="text" name="query" />
<input type="submit" value="Search" />
<% } %>
<div id="movieTable">
<% Html.RenderPartial("_MovieTable", Model); %>
</div>
A partial view encapsulates the section of the page you want to update.
<%# Control Language="C#" Inherits="ViewUserControl<IEnumerable<Movie>>" %>
<table>
<tr>
<th>
Title
</th>
<th>
ReleaseDate
</th>
</tr>
<% foreach (var item in Model)
{ %>
<tr>
<td>
<%= Html.Encode(item.Title) %>
</td>
<td>
<%= Html.Encode(item.ReleaseDate.Year) %>
</td>
</tr>
<% } %>
</table>
Then setup your controller action to handle both cases. A partial view result works well with the asych request.
public ActionResult Index(string query)
{
var movies = ...
if (Request.IsAjaxRequest())
{
return PartialView("_MovieTable", movies);
}
return View("Index", movies);
}

Basically the 'traditional' server-controls (including the ASP.NET AJAX ones) won't work out-of-the-box with MVC... the page lifecycle is pretty different. With MVC you are rendering your Html stream much more directly than the abstracted/pseudo-stateful box that WebForms wraps you up in.
To 'simulate' an UpdatePanel in MVC, you might consider populating a <DIV> using jQuery to achieve a similar result. A really simple, read-only example is on this 'search' page
The HTML is simple:
<input name="query" id="query" value="dollar" />
<input type="button" onclick="search();" value="search" />
The data for the 'panel' is in JSON format - MVC can do this automagically see NerdDinner SearchController.cs
public ActionResult SearchByLocation(float latitude, float longitude) {
// code removed for clarity ...
return Json(jsonDinners.ToList());
}
and the jQuery/javascript is too
<script type="text/javascript" src="javascript/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
// bit of jquery help
// http://shashankshetty.wordpress.com/2009/03/04/using-jsonresult-with-jquery-in-aspnet-mvc/
function search()
{
var q = $('#query').attr("value")
$('#results').html(""); // clear previous
var u = "http://"+location.host+"/SearchJson.aspx?searchfor=" + q;
$("#contentLoading").css('visibility',''); // from tinisles.blogspot.com
$.getJSON(u,
function(data){
$.each(data, function(i,result){
$("<div/>").html(''+result.name +''
+'<br />'+ result.description
+'<br /><span class="little">'+ result.url +' - '
+ result.size +' bytes - '
+ result.date +'</span>').appendTo("#results");
});
$("#contentLoading").css('visibility','hidden');
});
}
</script>
Of course UpdatePanel can be used in much more complex scenarios than this (it can contain INPUTS, supports ViewState and triggers across different panels and other controls). If you need that sort of complexity in your MVC app, I'm afraid you might be up for some custom development...

If you are new to asp.mvc I recommend you to download the NerdDinner (source) sample application. You will find in there enough information to start working effectively with mvc. They also have ajax examples. You will find out you don't need and update panel.

Related

In an MVC view, what controller and method is called if none is specified in the form tag?

I have a MVC project I inherited. On the views, there's no route (controller and action) specified in the BeginForm tag. The view renders correctly so I assume it is picking a default route.
My question is how does it know what route to use if one isn't specified? What's the best practice here: should you specify a route or let it default?
So the view is Views/Config/WorkCodes.cshtml and the tag is
Html.BeginForm()
It goes to the controller ConfigController.cs and calls action WorkCodes(). If I was doing the project, I would have wrote
Html.BeginForm("WorkCodes", "Config", FormMethod.Post)
How does MVC know which controller and action to use without specifying it?
WorkCodes.cshtml
#{
ViewBag.Title = "Work Codes";
}
#using (Html.BeginForm())
{
<div>
<table style="width: 100%;" class="trHoverHighlight">
<tbody>
<tr>
<td>
<br />
<div>
<button id="buttonCreateNew" type="button">Add New</button>
<button id="buttonReturn" type="button">Return</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
}
ConfigController.cs
public ActionResult WorkCodes()
{
return View(Rep.GetWorkAll(true));
}
Here's where the view is called from in another view:
#foreach (var itm in (List<string>)ViewBag.ListObjects)
{
<li>
Work Codes
</li>
}
The View is generated from performing HTTP GET to the WorkCodes controller action, thus by default the form generated in that view performs an HTTP POST to a controller action with the same name.
Here's the MSDN docs.
BeginForm(HtmlHelper) Writes an opening tag to the response.
The form uses the POST method, and the request is processed by the
action method for the view.

ASP.NET MVC - Delete rows in a table and then update database

In my yahoo email the inbox is displayed as a list of email items. Clicking on the item displays its detail. Now, back to the inbox. One of the columns in the list is a checkbox. If I click one or more checkboxes and then click "delete" then all those items are deleted.
That's more or less what I'd like to achieve with my ASP.NET MVC application. I have a table with some rows in it and I can tick some checkboxes to delete the selected rows and update the database.
I am coming from an Web Forms background. If the delete button is clicked it will do a post back and I can inspect in my code behind what items need to be removed. I am doing this, however, in ASP.NET MVC and I do not have the benefit of postback or view state. I figure this could be achieved with AJAX but I'd like to have a simpler solution, like a simple form post. Unfortunately, I do not know where to start.
At this point I can delete the rows on the client side with JQuery but I don't have anything on the database part as yet. Any tips is highly appreciated.
Below is my view code:
#model IEnumerable<Simplex.Data.Models.MessageBoardModel>
#{
ViewBag.Title = "Message Board";
}
<script type="text/javascript">
function deleteItems() {
$('.td_checkbox:checked').closest('tr').closest(tr).remove();
}
$(document).ready(function () {
$('#btnDelete').click(function () {
deleteItems();
});
});
</script>
<div id="content">
<h2>Board List</h2>
#{ Html.RenderAction("search", "home"); }
<div class="board_list">
<table>
<tr>
<th>
No
</th>
<th>
Subject
</th>
<th>
Posted By
</th>
<th>
Posting Date
</th>
</tr>
#foreach (var item in Model) {
<tr id=#item.Id>
<td>
#Html.DisplayFor(modelItem => item.Id)
</td>
<td class="subject">
<input class="td_checkbox" type="checkbox" /> #item.Subject
</td>
<td>
#Html.DisplayFor(modelItem => item.Username)
</td>
<td>
#Html.DisplayFor(modelItem => item.DatePosted)
</td>
</tr>
}
</table>
<button id="btnDelete">Delete</button>
<input type="button" value="Post" />
</div>
First Issue, don't use the #foreach, that strips out the built-in collection handling. Use #Html.DisplayForModel() instead. This will correctly create the proper indexed item names and id's.
Then in your HttpPost handler, you will want to have the parameter be the collection, and you can walk the list and see which checkboxes are set.
Use a for loop to render the following for each message:
<input name="messages[#i.ToString()].Key" type="hidden" value="#item.Id" />
<input name="messages[#i.ToString()].Value" type="checkbox" value="true" />
Then capture the POSTed values in your action like this
[HttpPost]
public ActionResult Delete(Dictionary<int,bool> messages)
{
IEnumerable<int> idsOfItemsYouWantToDelete = messages.Where(pair => pair.Value).Select(pair => pair.Key);
// Do delete, return redirect or whatever
}
This works because Dictionary<int,bool> is a collection of KeyValuePair<int,bool>s and the .Key and .Value input fields will be matched with the .Key and .Value properties of KeyValuePair<TKey, TValue>.
You may want to read ASP.NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries

Make a ASP.Net MVC Site, filtering the content

I recently started an MVC project to query and to report the company's users, everything seemed to be fine, except when I made a finduser form, I got all stuck!
you see I want the operator to be able to find the appropriate user by entering either hos pin,serial or calling number but the action links I make for the search operation all fail because they are made at the form_load time and so the empty string of text boxes get injected to them.
So my requests are:
How to make this filters work.
Now a little Ajax textbox suggester on user pin or serial would be great, please gimme a hint or two.
<table>
<tr>
<td>
PIN:</td>
<td>
<asp:TextBox ID="txt_pin" runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td>
Serial Number:</td>
<td>
<asp:TextBox ID="txt_sn" runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td>
CallingNumber:</td>
<td>
<asp:TextBox ID="txt_callingNo" runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td>
CalledThisNumberToday:</td>
<td>
<asp:TextBox ID="txt_calledNo" runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td>
</td>
<td>
</td>
</tr>
<tr>
<td>
</td>
<td>
</td>
</tr>
</table>
<%:Html.ActionLink("Search for user", "Details", new { pin = txt_pin.Text })%>
<asp:TextBox>? In an ASP.NET MVC application? I am afraid you got it all wrong.
I would recommend you going through the getting started tutorials here in order to learn the basic concepts of ASP.NET MVC: http://asp.net/mvc
In ASP.NET MVC you use models and in the views you use helpers in order to generate input fields.
So in your case you could design a view model:
public class SearchViewModel
{
public string Pin { get; set; }
public string SerialNumber { get; set; }
public string CallingNumber { get; set; }
public string CalledThisNumberToday { get; set; }
}
then you could design a controller action which will pass this view model to the view for rendering the search form:
public ActionResult Index()
{
var model = new SearchViewModel();
return View(model);
}
and finally in your strongly typed view you would use HTML helpers:
<%# Page
Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<AppName.Models.SearchViewModel>" %>
<asp:Content ID="MainContent" ContentPlaceHolderID="MainContent" runat="server">
<%= Html.ValidationSummary() %>
<% using (Html.BeginForm()) { %>
<div>
<%= Html.LabelFor(x => x.Pin) %>
<%= Html.EditorFor(x => x.Pin) %>
</div>
<div>
<%= Html.LabelFor(x => x.SerialNumber) %>
<%= Html.EditorFor(x => x.SerialNumber) %>
</div>
<div>
<%= Html.LabelFor(x => x.CallingNumber) %>
<%= Html.EditorFor(x => x.CallingNumber) %>
</div>
<div>
<%= Html.LabelFor(x => x.CalledThisNumberToday) %>
<%= Html.EditorFor(x => x.CalledThisNumberToday) %>
</div>
<p><input type="submit" value="Search for user" /></p>
<% } %>
</asp:Content>
and the final step would be to implement the controller action that will perform the search and to which this form will be subimtted:
[HttpPost]
public ActionResult Index(SearchViewModel model)
{
if (!ModelState.IsValid)
{
// the model was not valid => redisplay the form
// so that the user can fix his errors
return View(model);
}
// TODO: perform the search
...
}
Along with Darin's excellent answer (which you really need to follow in order to do things the "MVC" way...), you can also do AJAX filtering on a table using jQuery. There's even a plugin for jQuery that makes live table filtering as simple as adding a script reference and a textbox, then a couple lines of Javascript code to wire up the search. This will end up looking something like this:
<script language="javascript" type="text/javascript" src="/Scripts/jquery.js"></script>
<script language="javascript" type="text/javascript" src="/Scripts/jquery.uitablefilter.js"></script>
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$("#myFilter").keyup(function () {
$.uiTableFilter($("#myTable"), $(this).val());
});
});
</script>
<input type="text" id="myFilter" />
<table id="myTable">
...
</table>
As you start typing in the filter box, the table will be automatically filtered to only show rows that contain the specified value.
As for auto-complete suggestions, you might want to look into jQUery UI - they've got
support for auto-complete using several different mechanisms to provide the hint values.

ASP.NET MVC - PartialView not refreshing

I have a user control: VendorDDL.ascx, with the following code:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<List<MeetingCalendar.Models.Vendor>>" %>
<table>
<tr>
<th></th>
<th>
VendorId
</th>
<th>
VendorName
</th>
</tr>
<% foreach (var item in Model) { %>
<tr>
<td></td>
<td>
<%= Html.Encode(item.VendorId) %>
</td>
<td>
<%= Html.Encode(item.VendorName) %>
</td>
</tr>
<% } %>
</table>
My view: Create.aspx, has the following code snippet:
<p>
<label for="VendorNameSearch">Vendor Name:</label>
<input type="text" name="VendorNameSearch" id="VendorNameSearch" style="width:100px" />
<input type="submit" value="search" />
</p>
<% Html.RenderPartial("VendorDDL", MeetingCalendar.Controllers.HomeController.VendorsToSelect); %>
And everything works fine when I load up the Create view. The VendorDDL control is populated with the default values that are found in the VendorsToSelect. My controller has a List<Vendor> VendorsToSelect, which is getting updated properly.
Here is the problem: when the user clicks the SEARCH button, this fires off code in the Controller: return PartialView("VendorDDL", VendorsToSelect); I can see that VendorsToSelect is getting populated correctly based upon the user search.
I can step through the code, line-by-line, and see that immediately after return PartialView("VendorDDL", VendorsToSelect);, the debugger goes directly to the VendorDDL.ascx, and I can see that the Model is properly populated with the new VendorsToSelect, and the item.VendorId and item.VendorName are showing the correct values. But when debugging is done, and the Create view is shown, the VendorDDL control is not showing the new data.
Any suggestions?
I think that the output of your controller is discarded because the view (Create) has the same Html.RenderPartial("VendorDDL", MeetingCalendar.Controllers.HomeController.VendorsToSelect) as during initial load.
If I understand your problem correctly (and admittedly, without looking at the controller I may not) - you need to pass the model dynamically. The simplest (but not the most efficient) way would be to have jquery call $.load("/Home/VendorDDL") that would populate with the whole model; and then on submit hijax the form and pass form data to the same controller action.

Creating your own table with CommandArgument buttons in ASP.NET MVC

I'm trying to implement something like this:
<div>
<table>
<thead>
<tr>
<td>Port name</td>
<td>Current port version</td>
<td>New port version</td>
<td>Update</td>
</tr>
</thead>
<% foreach (var ip in Ports) { %>
<tr>
<td>
<%= ip.PortName %>
</td>
<td>
<%= ip.CurrentVersion %>
</td>
<td>
<%= ip.NewVersion %>
</td>
<td>
<asp:Button ID="btnUpdate" runat="server" Text="Update" CommandArgument="<% ip.PortName %>" />
</td>
</tr>
<% } %>
</table>
</div>
The button's CommandArgument property is where my code complains about not being able to resolve symbol ip. Is there any way to do what I'm trying to do?
­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
You don't want to use a Webforms button in ASP.NET MVC. MVC is a completely different way of working, and you no longer have the WebForms abstraction.
You have 2 different options you can either replace your asp:Button with an input tag or use a standard hyperlink instead. If you use the input option then you will need to wrap in a form element. The form action should point to a Controller action.
You can't use webform controls in ASP.NET MVC in a trivial manner because they rely on things that are stripped out in MVC. Instead you add a button in two ways, both using the HtmlHelper on the ViewPage:
You can add a button in a form, which is easily handeled in a controller if you have a form for each single button:
<% using(Html.BeginForm("Update", "Ip", new {portName = ip.PortName} )) { %>
....
<input name="action" type="submit" value="Update">
<% } %>
BeginForm() will default to the same controller and action as the view was created from. The other way is to add a link instead, which is more fitting to your example of iterating through a list. For example lets say you have IpController
<%= Html.ActionLink("Update IP", "Update", "Ip",
new {
portName = ip.PortName
})
%>
The link will go to the Update action in IpController with the given portName as parameter. In both cases you'll need this action in IpController:
public ActionResult Update(string portName) {
// ...
}
Hope this helps.
I think you have to enclose your block in Form tags ans runat=server.
FWIW,
I think this text is missing an equals sign:
CommandArgument="<% ip.PortName %>"
Should be
CommandArgument="<%= ip.PortName %>"

Resources