Editable "GridView" like control in ASP.NET MVC - asp.net-mvc

I'm trying to build a Editable GridView like control (Order column) with this code in the view:
<table>
<tr>
<th>
Name
</th>
<th>
Order
</th>
<th>
<img alt="Save order" src="<%= Url.Content("~/Content/minisave.png") %>" />
</th>
<th></th>
</tr>
<% foreach (var item in Model) { %>
<tr>
<td>
<%= Html.Encode(item.Name) %>
</td>
<td colspan="2">
<%= Html.TextBox("Order", item.Order, new { size = "3" }) %>
</td>
<td>
<%= Html.ActionLink("Edit", "Edit", new { id=item.id }) %> |
<%= Html.ActionLink("Details", "Details", new { id=item.id })%>
</td>
</tr>
<% } %>
</table>
The result table look like:
The questions are: How I receive this data in my controller? I need a form tag around the table? How I know which Order value belongs to which record?
A couple extra questions: If you see the code I add the size attribute to the input tab but when the browser renders it, the input is larger, how can I fix it?
Thanks for your help!

I've done this before. I did it by having the ID as part of the name, and a form around the entire table. That way the controller pulled all the data from all the rows and updated it all at once like a spreadsheet.
That works well for a unit of work, where you edit the page and save it, though of course you'd need to consider how to cope with your locking strategy, be it optimistic or pessimistic.
However, these days a better alternative might be to use ajax to submit specific values, somewhat like Google Spreadsheet, maybe?

Related

MVC Turn model text into clickable link

I have an MVC Razor view that pulls change log information from a database (a table which only I have access to, limiting security concerns).
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Description)
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
</tr>
}
</table>
The description will contain values like New page available: http://localhost:0000/app/NewItem. What I'm trying to figure out is how to make that web address active.
I.e., turn New page available: http://localhost:0000/app/NewItem
into: New page available: http://localhost:0000/app/NewItem
and have the link properly rendered on the page. Is there a simple way to accomplish this, short of using regular expressions in the controller to pull that link out?

When using MVC, how to call a Controller Action and Pass Text Box values?

How to read from a text box value when using Html.ActionLink so that the value can be passed to the action?
I have the below code:
<table>
<tr>
<th>
Consumer Key:
</th>
<td>
#Html.TextBox("ConsumerKey")
</td>
</tr>
<tr>
<th>
Consumer Secret Key:
</th>
<td>#Html.TextBox("ConsumerSecretKey")
</td>
</tr>
<tr>
<th>
</th>
<td>#Html.ActionLink("Retreive Access Tokens", "/Retrieve"</td>
</tr>
</table>
Basically, I'd need to call the Controller Action and pass the text box values.
How would that be possible with MVC?
I know I can implement it using just an html button and an AJAX call to that Action but I hoped there would be another way using MVC controls.
By putting your code inside the Html.BeginForm("Retrieve", "Twitter") block, the html that is rendered to the browser will be enclosed inside a form-tag, something like:
<form method="POST" action="/Retrieve/Twitter">
<table>...</table>
</form>
Then when you click on the submit button the form, along with all the values in the text boxes will be posted to you MVC application. Then MVC does the work of mapping these form values (the text boxes created using #Html.TextBox("ConsumerSecretKey") and their values) to the parameters of your controller actions.
In your case, roughly the following will be rendered to the browser (the action link will need to be changed to an input of type "submit," as I have done below:
<form method="POST" action="/Retrieve/Twitter">
<table>
<tr>
<th>
Consumer Key:
</th>
<td>
<input id="ConsumerKey" name="ConsumerKey" type="text" value="" />
</td>
</tr>
<tr>
<th>
Consumer Secret Key:
</th>
<td>
<input id="ConsumerSecretKey" name="ConsumerSecretKey" type="text" value="" />
</td>
</tr>
<td><input type="submit" id="Retrieve" value="Retreive Access Tokens" /></td>
</tr>
</table>
</form>
When this is posted back to your Application the text you entered into the text boxes (rendered as tags) would map to the parameters of your action method matching their name:
public ActionResult Retrieve(string consumerKey, string consumerSecretKey)
{
//action method code here
}
The concept at work here is called model-binding. See Controllers and Action Methods in ASP.NET MVC Applications and scroll down to the "Action Method Parameters" section for an overview
I used, Html.BeginForm with a submit button, then oddly the textbox values are submitted to the server automatically:
#using (Html.BeginForm("Retrieve", "Twitter"))
{
<table>
<tr>
<th>
Consumer Key:
</th>
<td>
#Html.TextBox("ConsumerKey")
</td>
</tr>
<tr>
<th>
Consumer Secret Key:
</th>
<td>#Html.TextBox("ConsumerSecretKey")
</td>
</tr>
<tr>
<th>
</th>
<td>
<input type="submit" id="Retrieve" value="Retreive Access Tokens" />
</td>
</tr>
</table>
}
And in my Controller Action:
public ActionResult Retrieve(string consumerKey, string consumerSecretKey)
{
}
You can use FormCollection object.
[HTTPPost]
public ActionResult Retrieve(FormCollection collection)
{
string consumerKey=collection["ConsumerKey"];
string consumerSecretKey=collection["ConsumerSecretKey"];
}
Use form post method by using a submit button in your form.
In reality you cannot POST using Html.ActionLink. You can achieve that using Ajax.ActionLink and setting AjaxOptions properties. If using form is not an option for you, you can always implement jQuery function that intercepts a click generated by Html.ActionLink (based on an ID generated by this helper) and add a value from text box as a parameter. The problem here is that if you don't use Ajax you will submit the values using GET method and this is a big NO. GET should be used for retrieving values, and not for modifying the contents of a database or other backend data store. If you plan to use Ajax you could do something like this:
$(document).ready(function() {
$("myActionLinkId").click(function() {
var textBoxValue = $("#myTextBoxId").val();
$.post($(this).attr("href"), { id: textBoxValue }, function(result) {
alert("Result data: " + result);
});
});
});

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.

Map path of local file ASP.NET/MVC

I have a file upload program written in ASP.NET MVC. It is currently on my local development machine, and I would like to know how (if it is possible) to generate a link for each uploaded file so when it is clicked, the item is displayed/downloaded etc.
Current code/markup that handles displaying file list:
<table>
<tr>
<th></th>
<th>
Name
</th>
<th>
Length
</th>
<th></th>
</tr>
<%
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "uploads");
foreach (var file in Directory.GetFiles(path))
{
var item = new FileInfo(file);
%>
<tr>
<td></td>
<td>
<%=Html.Encode(Path.GetFileName(item.Name))%>
</td>
<td>
<%=Html.Encode(item.Length >= 1024 ? item.Length / 1024 + " kilobytes" : item.Length + " bytes")%>
</td>
<td>
// This is the line in question. Does not work as-is.
<%= Html.Encode(Path.GetFileName(item.Name)) %>
</td>
</tr>
<% } %>
</table>
I imagine I will have to change the file-handling code around once this goes live, but for now this is sufficient. Suggestions are also welcome :)
Thanks!
Use Url.Content, e.g.:
<img src="<%= Url.Content("~/Content/UserImages/FileName.jpg") %>" />
The tilde means "the root of my site, wherever that happens to be." You don't have to put your files in Content; you can put them wherever you want under your site root.
Yes the appropriate equivalent to BaseDirectory in an ASP.NET app is HttpRuntime.AppDomainAppPath. However you might also find the Server.MapPath method useful. You get to the server method via HttpContext.Current.Server.
Having said that are you sure you want this sort of code in your view. Its seems to me that the list of values you want to display ought to be generated by the controller.
<a href="<%= Url.Content(System.Web.VirtualPathUtility.ToAppRelative("~/" + file.Substring(AppDomain.CurrentDomain.BaseDirectory.Length))) %></a>

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