MVC Turn model text into clickable link - asp.net-mvc

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?

Related

Paging in MVC 5

In MVC 5, how to create paging for table? The following is a table structure.
<table class="table">
<tr>
<th>
Item ID
</th>
<th>
Item Name
</th>
<th>
Rate
</th>
<th>
Stock
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.ItemID)
</td>
<td>
#Html.DisplayFor(modelItem => item.ItemName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Rate)
</td>
<td>
#Html.DisplayFor(modelItem => item.Stock)
</td>
</tr>
}
</table>
I recommend the PagedList package which is available on nuget
https://www.nuget.org/packages/PagedList
Here is the full documentation
https://github.com/TroyGoode/PagedList
This tutorial has a good explanation of paging and how to install and use the packages:
http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application
I have found the solution. Using webgrid, we can achieve the paging
#model IEnumerable<ItemMaster>
#{
ViewBag.Title = "Item Details";
WebGrid grid = new WebGrid(Model,rowsPerPage:5);
}
<h2>Item Details</h2>
#grid.GetHtml()
Grid.MVC is an open source and working Grid with sorting and paging
(and unlike telerik you do not need to change anything on controller side just add reference in your view and use.)
To install nugget package (Install)
PM> Install-Package Grid.Mvc -Version 3.0.0
In your view you can auto-create columns as below (or customize see User Guide)
#using GridMvc.Html
#Html.Grid(Model).AutoGenerateColumns()
See Online Demo
you can look for DataTables jquery plugin here. It is a very powerful and light weight plugin that supports sorting and searching inside the table.

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);
});
});
});

MVC 3 Razor view renders different on hosting environment than locally

I have created an MVC 3 view, just by adding a controller and scaffold it by usage of entity framework.
See below view:
<table>
<tr>
<th>
MetaType
</th>
<th>
Value
</th>
<th>
Page
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.MetaType)
</td>
<td>
#Html.DisplayFor(modelItem => item.Value)
</td>
<td>
#Html.DisplayFor(modelItem => item.Page.Title)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
#Html.ActionLink("Details", "Details", new { id=item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id=item.Id })
</td>
</tr>
}
</table>
When I open the view on my dev machine than the html produced is just as expected:
<table>
<tr>
<th>
MetaType
</th>
<th>
Value
</th>
<th>
Page
</th>
<th></th>
</tr>
<tr>
<td>
Keywords
</td>
<td>
bla, bla bla,
</td>
<td>
Home
</td>
<td>
Edit |
Details |
Delete
</td>
</tr>
On our hosting environment it's rendered with on almost every row an extra whiteline.
<table>
<tr>
<th>MetaType</th>
<th>Value</th>
<th>Page</th>
<th></th>
</tr>
<tr>
<td>Keywords</td>
<td>values, values, values.</td>
<td>Home</td>
<td>Edit | Delete</td>
</tr>
Anyone has an idea why there is a difference, and how to resolve this extra whitespace?
UPDATE
It seems like only this page is having this issue. Other pages just have a normal html layout as expected. I also have checked the data from the database, but can't find anything unusual or different than the other pages.
I have also tried to regenerate the file and upload it again, but also no luck. I'm a bit out of options on this issue.
When something different in a host comparing to your environment, it's usually one of the following issues:
Time and/or DateTime Format of server is different from your local machine
Global application culture and/or encoding is different
Databases (MS-SQL) has a different collisions
I suggest you to add the following node to both your local and host web.config, and check the result:
<configuration>
<system.web>
<globalization
requestEncoding="utf-8"
responseEncoding="utf-8" />
</system.web>
</configuration>
After a doing a republish of my application the issue has dissapeared. Haven't found what's causing it.

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

Editable "GridView" like control in 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?

Resources