Hi i'm building application in MVC and i want to use a display template to display my model in a view. This is my template, but it gives me error when I try to display it:
#*<tr>
<td>#Html.Display(NameE)</td>
<td>#Html.Display(NameC)</td>
<td>#Html.Display(NameR)</td>
<td>#Html.Display(Timespan) </td>
<td><button class="button" type="submit" name="Review"></button></td>
</tr>*#
I want this template to display each row filled with database data in the td's, but it is doing nothing. What am I doing wrong ?
First, try using #Html.DisplayFor(yourModel, "YourTemplateName") in your view.
When you are doing default templates you should relate them to the model and put them in your Shared folder so it will relate to them. In your case you should do model related DisplayFor:
#model YourModel
<tr>
<td>#Html.DisplayFor(x => x.NameE)</td>
<td>#Html.DisplayFor(x => x.NameC)</td>
<td>#Html.DisplayFor(x => x.NameR)</td>
<td>#Html.DisplayFor(x => x.Timespan) </td>
<td><button class="button" type="submit" name="Review"></button></td>
</tr>
Then in your controller you should just use it like this:
#Html.DisplayFor(Model)
Take a look at this article for more information. Hope this helps ;]
Related
I have an ASP.NET View using server-side #foreaches, now replaced with AngularJS.
Now I use ng-repeat="record in records", and I don't use anymore the #foreach.
The actual code that worked with #record.Id now does not work with {{record.id}}:
<td class="text-nowrap">
<a asp-controller="Records" asp-action="Edit" asp-route-id="{{record.id}}">Edit</a>
<a asp-controller="Records" asp-action="Details" asp-route-id="{{record.id}}">View</a>
<a asp-controller="Records" asp-action="Delete" asp-route-id="{{record.id}}">Delete</a>
</td>
obviously, because the #record.Id was on the server side...
Now, the solution I see it to set something like
However if the controller's route will change it could lead to nowhere... Is there a way to workaround that?
PS.
Some more code for better understanding:
<div ng-app="tablesApp" ng-controller="tablesController as tc">
<table>
<thead>
<tr>
<th>#Html.DisplayNameFor(model => model.Name)</th>
<th>#Html.DisplayNameFor(model => model.Description)</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="record in records">
<td>{{record.name}}</td>
<td>{{record.description}}</td>
<td>
<a asp-controller="Records" asp-action="Edit" asp-route-id="{{record.id}}">Edit</a>
<a asp-controller="Records" asp-action="Details" asp-route-id="{{record.id}}">View</a>
<a asp-controller="Records" asp-action="Delete" asp-route-id="{{record.id}}">Delete</a>
</td>
</tr>
</tbody>
</table>
</div>
JS Controller:
$http.get("/api/Records")
.then(function (response) {
tc.records = response.data;
}));
Actually a little bit better option that the hardcoded route is to use
<a href="#Url.Action(action: "Edit", controller: "Records")/{{record.id}}" ></a>
However this one is supposed to have the {ActionRoute}/{id} fixed structure...
In case you use foreach in razor view (obviously you do) then you can't use angular syntax {{record.id}} you have to use #record.id
But if you get records, as an array/list whatever, in AngularJs then you have to change your html and use ng-repeat
-- Edit
Sorry just see your code again, you used asp-action and asp-controller etc
They are TAG HELPERS from core version, in other words they will get rendered on the server side and what you will get in the browser actually is anchor link like
<a href="/Records/Edit/{{record.id}}" >Edit</a>
AngularJs as you know is client side so it won't render. Either use #Url.Action as you already did or you could remove asp-route-id and add the id later using custom directive.
How do I make the HTML table display 10 records only and whenever it goes beyond 10 it will display a link for pages below? e.g. "1, 2, 3.." And limits up to 7 links like how YouTube displays it (See image below)? I'm using ASP.Net MVC with Bootstrap by the way.
<table id="userTbl" onclick="getTblRec('userTbl,'userBody','0')" class="table-scroll table-striped bootgrid-table">
<thead>
<tr>
<th class="hidden">
#Html.DisplayNameFor(model => model.USR_ID)
</th>
<th class="hidden">
#Html.DisplayNameFor(model => model.USR_FNAME)
</th>
</tr>
</thead>
<tbody id="userBody">
#foreach (var item in Model)
{
<tr>
<td id="userId" class="hidden">
#Html.DisplayFor(modelItem => item.USR_ID)
</td>
<td>
#Html.DisplayFor(modelItem => item.USR_FNAME)
</td>
<td>
</tr>
}
</tbody>
</table>
YouTube sample pic:
There are two ways of implementing pagination, Server and Client side. Firstly server implementation, Load only the set of items that are to be shown for the page from the server along with the page options. Pagination at the client side, load the entire set of items and provide pagination with the support of table and/or other controls. Both the options have pros and cons. These links should get you started on the topic,link1 , link2.
Since you are using ASP.NET MVC, there is an build in helper named WebGrid for scenarios like paging. This is super easy to use and provides almost all the functionality that you may need.
You can also take a look at this beginner level walk through.
WebGrid in asp.net mvc (By Sheo Narayan).
Make a partial view for paging and call that partial view if records you have more than 10. i.e. in this link Paging
Or you can install this nuget also, and your wish style would be able to design this is link for nuget Nuget Packege
The model that is being displayed in my view has been filtered by user action so some of the original data is no longer there. Paying attention to the ActionLink for EditRow, this is how my view displays the model:
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.User.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.User.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.User.Email)
</td>
<td>
#item.Weekly.WeekBeginning.ToShortDateString() - #item.Weekly.WeekEnding.ToShortDateString()
</td>
<td>
#(item.WeeklyTargetId != ViewBag.Edited ? Html.DisplayFor(modelItem => item.Hours) : Html.EditorFor(modelItem => item.Hours))
</td>
<td>
//here is the line I am trying to pass the model through:
#Html.ActionLink("Edit", "EditRow", new {id = item.WeeklyTargetId, currentSelection = Model}) |
#Html.ActionLink("Details", "Details", new {id = item.WeeklyTargetId}) |
#Html.ActionLink("Delete", "Delete", new {id = item.WeeklyTargetId})
</td>
</tr>
}
In the ActionLinkfor EditRow I was able to easily pass the id of each item through, but when I added currentSelection = Model or even = Model.ToList(), the controller method receives a count of 0.
Here is the Action signature I am using:
//I've tried IQueryable<WeeklyTarget> as well
public ActionResult EditRow(int? id, List<WeeklyTarget> selection )
My question is how can I pass the current(filterd) model being displayed in the view to the controller action? Should I be going about this a different way?
This is not the correct way to implement this, but if you MUST do it this way you would be better off passing the Ids from each item in Model rather than the Model objects themselves. Then in the Edit (GET) method, you can get those full objects from the DB using those IDs.
The intention of this code is not clear to me though. If every row has an "Edit" link, then I would assume that clicking that would only care about that specific row and not the entire list. More detail would be helpful to better answer the question.
UPDATE:
As discussed below, the best way to go about this would be with AJAX(recommend using jQuery). Upon click on a edit link, you should initiate a click handler in JS:
$(".editLink").click(function(){
//Code Here
});
The logic for the click function will be to grab the data from the row and make an AJAX Post back to a controller action.
$.post(urlToAction, data, succuessFunction);
This will work perfectly for you, however you will have to do a lot of the data insert, update, delete operations manually. There are some pretty handy JS frameworks out there like Knockout JS which will handle this automatically for you after a little wiring/plumbing work up front.
I suggest you check those out.
I have an existing web application built using ASP.NET WebForms and I am converting it to MVC 4.0. I have an administrative page that allows user to do CRUD operations on same page for employee such as edit address or add multiple addresses at same time by dynamically adding usercontrols. I have implemented ListView for displaying, editing and saving on same page. Now if I want to achieve same thing i.e. display/Edit/Save on the same view in MVC could someone suggest good practices for such scenario. (p.s. I have partial views ready for such CRUD operations)
Any help will be greatly appreciated.
Yes there are many way you can achieve this in MVC. Just like ListView,there are many third party controls which acts as ListView in MVC. But if you don not want to use those third party controls,then you can go with Table,Tr and Td. For that purpose, lets take an example. Your model is returning the list of data so that you need to display that list on the View. So get that list and use foreach loop and just use Table,TH,TR and TD. You can use #Html.ActionLink for Edit,Delete,etc. Hope this will help you.
I have implemented the similar thing in the MVC:
View:
// Creating html Table from data present in model
<table class="content-wrapper">
<tr>
<th>
#Html.DisplayName("Name")
</th>
<th>
#Html.DisplayName("ID")
</th>
<th>
#Html.DisplayName("Designation")
</th>
<th>
</th>
</tr>
#foreach (var item in Model.lstEmployees)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.name)
</td>
<td>
#Html.DisplayFor(modelItem => item.id)
</td>
<td>
#Html.DisplayFor(modelItem => item.designation)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.id })
#Html.ActionLink("Delete", "Delete", new { id = item.id })
</td>
</tr>
}
Controller:
public ActionResult Delete(Data model)
{
//Code for delete
return View("Index", data);
}
[HttpGet]
public ActionResult Edit(Int32 Id)
{
//code for binding the existing records
return View(_data);
}
[HttpPost]
public ActionResult Edit(string sampleDropdown, Data model)
{
//code for saving the updated data
return RedirectToAction("Index", "Home");
}
As I wanted to use the same view to show/edit/save, I found a solution to implement AJAX and render partial views for CRUD operations. This can be achieved in many ways but I selected two options:
Using #Ajax.BeginForm and jquery.unobtrusive-ajax.min and just fetching partialview.
Using jQuery AJAX to acheive this.
Here is a link I found in Stackoverflow very helpful:
Using Ajax.BeginForm with ASP.NET MVC 3 Razor
(Thanks all for your effort)
We have a small Asp.Net MVC project which displays a report of several tens or hundreds of rows of data. Each row is represented by an object on the view models.
Currently we are showing the rows like this:
<table>
<tr style="text-align:center">
<th>Name</th>
<th>Item count</th>
<th>Stat 1</th>
<th>Stat 2</th>
<th>Etc</th>
</tr>
<% var alternating = false;
foreach(RowItem rowItem in Model.RowItems)
{ %>
<%= Html.BeginRow(alternating) %>
<%= Html.ShowRow(rowItem) %>
<% alternating = !alternating; %>
<%= Html.EndRow() %>
<% } %>
</table>
Where BeginRow, EndRow and ShowRow are helper extension methods that I wrote. ShowRow is something like
public static string ShowRow(this HtmlHelper html, RowItem rowItem)
{
return "<tr><td>.... </tr>";
}
But I could also replace Html.ShowRow(rowItem) with another partial view, i.e. Html.RenderPartial("RowControl", rowItem);
The question is, what are the advantages and drawbacks of these two approaches? All I can think of is that the partial view is more "designable" - easier to work with when the amrkup is complex, and by team members who specialise in "design" and "client development", i.e. html, css and javascript not c#. The HTML helper method is a just assembling a string containing the required html, which appeals to an old-school coder.
Which one, if any, has noticeable performance implications over hundreds of items? Are there maintenability impacts for either of them? All other things being equal, which would you choose to use?
We are on Asp.Net MVC 1.0 and Visual Studio 2008, but will probably upgrade some time in the next few months.
I'm not sure how well known this is (I just found out by playing around myself), but you can actually use anonymous methods to define chunks of your page content, so that is an alternative to defining a separate partial view. I find this especially useful when just have a small chunk of HTML/server code that I want to reuse, or if I don't want to define a complex Model/ViewData contract between a partial view and the calling view.
Below is an example of some code embedded in a view:
// define example data
IEnumerable<MyDataItem> data = new MyDataItem[] {
new MyDataItem { Id = 1, Value = "ABC" },
new MyDataItem { Id = 1, Value = "BCD" },
new MyDataItem { Id = 1, Value = "CDE" },
new MyDataItem { Id = 1, Value = "DEF" },
};
// an anonymous method to define reused HTML/server code
Action<MyDataItem> displayData = delegate(MyDataItem item)
{
%><span class="my-data-class" title="This is my data!"><%= item.Value %></span><%
};
%><div><%
// use the displayData delegate to render a table
%><table><%
foreach (MyDataItem item in data)
{
%><tr><td><% displayData(item); %></td></tr><%
}
%></table><%
// use the displayData delegate to render a set of divs
foreach (MyDataItem item in data)
{
%><div><% displayData(item);%></div><%
}
%></div><%
The above example renders the following HTML (formatted for clarity):
<div>
<table>
<tr>
<td>
<span class="my-data-class" title="This is my data!">
ABC</span>
</td>
</tr>
<tr>
<td>
<span class="my-data-class" title="This is my data!">
BCD</span>
</td>
</tr>
<tr>
<td>
<span class="my-data-class" title="This is my data!">
CDE</span>
</td>
</tr>
<tr>
<td>
<span class="my-data-class" title="This is my data!">
DEF</span>
</td>
</tr>
</table>
<div>
<span class="my-data-class" title="This is my data!">ABC</span>
</div>
<div>
<span class="my-data-class" title="This is my data!">BCD</span>
</div>
<div>
<span class="my-data-class" title="This is my data!">CDE</span>
</div>
<div>
<span class="my-data-class" title="This is my data!">DEF</span>
</div>
</div>
When creating views for MVC projects, I generally try to keep all of the same element generation in the same view. So for your case, since you are creating a table, I would make sure that all table tags are created inside the same view. This helps ensure that you are creating well formed HTML and makes tracking down validation issues much easier.
I don't really like what is going on here so much for a couple of reasons. The show row extension is likely taking some kind of custom HtmlTableRow object as its input, which likely has a collection of HtmlTableCell objects in it, each of which has stylistic properties set on it. Since these HtmlTableRows are created in your controller, it tightly couples your presentation to your controller which defeats the separation of concerns principle of MVC.
Next, if you replace ShowRow with a render partial, it will not follow the guideline I suggest in the first paragraph by rendering tags for the same element in different views. Occasionally you can get away with rendering your elements in different functions, but if you do so, the objects they return should implement the disposable pattern and only be implemented with using statements.
If I were going to modify this so that designers could have more control over the design, I would render the table all in one partial view, and I would give every cell a descriptive class name. I would also take the entire table and put it in a partial view, even if it were the only thing on this page.