Previous post
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%
MvcApplication1.Models.FeaturesRepository _model = new MvcApplication1.Models.FeaturesRepository();
%>
<% foreach (var md in _model.GetAllFeatures())
{ %>
<li><%= md.vcr_FeaturesName %></li>
<% } %>
It is with reference to the previous post above.Is there something wrong with the foreach loop(The result is correct but it is displaying the series of Add,Add,Add,Add,Add,Add...,which is the last record of the getallfeatures.
#mazhar, instead of creating your model like you are, in MVC you should return the model to the view.
In your controller you would say something like return View(MyModel);
I don't see anything wrong, per-sey, with your foreach but if you are going to replicate a control over and over you may want to consider a PartialView and rendering that by passing the appropriate model to it.
<% foreach ( var md in model.features ) Html.RenderPartial(md); %>
The above is untested but close I think.
I haven't looked at the previous post because I think you need to get this into the MVC way first. I don't think there is technically anything incorrect in your code and suspect it's your controller and model code.
I've edited your post to remove the commented out code. Very confusing leaving it in.
Related
I'd like have the following type of code fragment in a .aspx page:
<% foreach( int i in <some-expression> ) { %>
<asp:linkbutton CommandArgument="<value-of-i>" OnClick="<some-handler>" runat="server" />
<$ } %>
Basically, I want to generate the page sans data binding, but supply the value of CommandArgument to the linkbutton from a variable in the code behind, so that when the click handler activates, I can retrieve the value of the variable from the CommandArgument, that existed when the code ran.
I do not want to use data binding, for various reasons. Is this possible? I understand that the <%: ... %> syntax is equivalent to Response.Write, and that the syntax <%# %> retrieves values which are databound. I also know that I can't use the <%: %> syntax here to solve my problem. And because I am not using data binding, I can't use the <%# %> syntax.
It seems to me that something like this should be very basic.
So, to answer my own question, there seems to be no way to mix server side controls and state generated from the code around them. The reason being that server side controls are generated before the code runs, and the code, for the most part, runs to emit the response (think Response.Write).
However, one can "manually" cause the post back that server side controls, like asp:LinkButton, perform with a java script call to __doPostBack. So the solution to my problem is something like the following:
<% for( int i = 0; i < 10; i++ ) { %>
<a href="" onclick='javascript:__doPostBack( "MeClicked", "<%: i %>" ); return false; '>Click Me <%: i %></a>
<% } %>
Where Page_Load does something like::
if ("MeClicked".Equals( Request.Form[ "__EVENTTARGET" ] )) {
string arg = Request.Form[ "__EVENTARGUMENT" ];
Response.ClearContent();
Response.Write( arg + " Clicked" );
Response.End();
return;
}
i have written the following code in my view and i have to print value of variables of my forloop variables company in my view how can i do this
<table><tr>
<td>
<%
var ResDet1 = (from r in db.Res_Exp
where r.Resume.ResumeID == 191
select new{r.ResExpID,r.Company}).ToList();
string company;
int exprinceid;
if (ResDet1 != null)
{
foreach (var rc in ResDet1)
{
exprinceid = rc.ResExpID;
company = rc.Company;
}
}
%>
</td></tr></table>
i believe following code
var ResDet1 = (from r in db.Res_Exp
where r.Resume.ResumeID == 191
select new{r.ResExpID,r.Company}).ToList();
belongs to repository and
string company;
int exprinceid;
should be included in your model. Only foreach should appear in the view. In your controller you should call method of your repository and wrap everything in a view model and pass it to the view. In view you should only iterate and render values (either in display mode or in edit mode). Look at this question for how to implement repository pattern in asp.net mvc
Answer - as requested.
Why use a loop? Make use of MVC's templating.
Create a display template called MyModel, where MyModel is whatever type ResDet1 is:
Shared\DisplayTemplates\MyModel.cshtml
<tr>
<td><% Html.DisplayFor(model => model.ResExpID) %></td>
<td><% Html.DisplayFor(model => model.Company) %></td>
</tr>
Then your main View simply becomes this:
<table>
<% Html.DisplayForModel() %>
</table>
How does that work? Well, your View should be strongly-typed to an IEnumerable<ResDet>, which as #Muhammad mention's, should be fetched via a Repository.
Your action should be something like this:
[HttpGet]
public ActionResult Index()
{
var results = _repository.ResDets();
return View(results);
}
Ideally, you should be using the Repository pattern to talk to the model, use AutoMapper to flatten the model into a ViewModel, and use interface-driven Dependency Injection to handle the dependencies (e.g _repository).
But if that's too much for you, at the very least, put the data access code in the action method, never, i repeat, never in the View.
Now isn't that nicer?
Controller has 2 lines of code - one to retrieve the model, another to call the View. Textbook stuff.
View is dumb. It renders out what it needs to, and is focused on presentation only.
The foreach loop is avoided, as MVC will do an implicit foreach loop, since it sees the model is of IEnumerable<Something>, so it looks for a template matching that Something, and finds your custom template.
Try not to forget the principles of MVC. If your mixing code and markup in your View, you've already lost and may as well be coding in classic ASP.
Usually you'd do something like:
<% foreach (var someVar in someCollection)
{ %>
<%: someVar %>
<% } %>
To print in a loop.
Well, presently, your foreach loop is running entirely within your view engine's code block. The code is running, and those variables are being reassigned a number of times, but you're never telling the C# to write any HTML. I don't write in ASPX, I write in the Razor, so I don't know much for how to escape in and out of C# mode, but I think it'd be something like this:
<table>
<%
var ResDet1 = (from r in db.Res_Exp
where r.Resume.ResumeID == 191
select new{r.ResExpID,r.Company}).ToList();
string company;
int exprinceid;
if (ResDet1 != null)
{
foreach (var rc in ResDet1)
{ %>
<tr>
<td><% rc.ResExpID; %></td>
<td><% company = rc.Company; %></td>
</tr>
<% }
}
%>
</table>
EDIT: To be specific, the point is that you want to leave the code to write HTML to the page, and return to finish the code block. As I understand it, MVC is consistent with this principal in both rendering engines.
I have a code like this in my controller.
ModelAndView result = new ModelAndView("person/sometrends");
result.addObject("data", data); // data -> Map
In my JSP page I have written some Java code that is dependent on the data object.
How can I get that data object within the JSP code?
I tried something like this (pseudo code).
<%
Map x = ${data};
%>
But that doesn't work. Not sure how to access it.
In a scriptlet, you use the request object like so:
<% Map myMap = (Map) request.getAttribute("data"); %>
If you want to use something like JSTL instead of a scriptlet, you could do:
<c:forEach var="entry" items="${data}">
Name: ${entry.key} <br/>
Value: ${entry.value} <br/>
</c:forEach>
As Davemeister and novice pointed out, combining EL inside a scriptlet was the root cause of your error.
Let me more specific, if you want to use jsp instead of jstl to access the Model you would do something like this:
<% Map x = (Map)request.getAttribute("data") %>
Try this:
request.getAttribute("data")
try<% String username = (String)request.getAttribute("data"); %>
Using expression language inside the scriptlet would be the cause.
include: <%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
and then...
<%
Map x = ${data};
%>
I'm trying to do this: Editing a variable length list, ASP.NET MVC 2-style
In the post he mentions that it could be done with less code using Html.EditorFor(), but that it would be more difficult because of the indexes. Well, that's exactly what I want to do, and I don't know where to begin.
I'm an ASP.NET novice who just completed the Nerd Dinner tutorial before jumping into a project at work, so any help would be appreciated.
Update 1: Instead of generating a GUID for each item in the collection, I'd like to generate incremental indexes starting with 0. Right now the field names look like "gifts[GUID].value"; I would like them to be "gifts[0].value","gifts1.value" etc. but I don't understand how the collection keeps track and generates these indices.
In response to your update about generating indexes instead of GUIDs, the original linked article had a few comments from others that tried to solve the same issue but none of them worked for me. What I found was the collection with index was referenced in the following location:
html.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix
So I wrote a helper function to parse out the index (and if there is a problem then the GUID would be generated)
public static string GetCollectionItemIndex(this HtmlHelper html, string collectionName)
{
int idx;
string sIdx;
if (Int32.TryParse(Regex.Match(html.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix, #"\d+").Value, out idx))
{
sIdx = idx.ToString();
}
else
{
sIdx = Guid.NewGuid().ToString();
}
return sIdx;
}
I edited the BeginCollectionItem(..) function to call this helper function when setting the item index:
string itemIndex = idsToReuse.Count > 0 ? idsToReuse.Dequeue() : GetCollectionItemIndex(html, collectionName);
Hope this helps someone else!
Well, you begin by defining an editor template (~/Views/Shared/EditorTemplates/Gift.ascx):
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MyApp.Models.Gift>" %>
<div class="editorRow">
<% using(Html.BeginCollectionItem("gifts")) { %>
Item: <%= Html.TextBoxFor(x => x.Name) %>
Value: $<%= Html.TextBoxFor(x => x.Price, new { size = 4 }) %>
<% } %>
</div>
And then replace the RenderPartial call with EditorForModel:
<% using(Html.BeginForm()) { %>
<div id="editorRows">
<%= Html.EditorForModel() %>
</div>
<input type="submit" value="Finished" />
<% } %>
Once you've tried this you may come back and ask if you have any problems by explaining the symptoms.
I am dynamically generating a table to present some tabular data. Normally I would not go near tables, but for this kind of data it is appropriate.
I am noticing my view code is becoming very spaghetti like. Assigning classes on cells and rows in the body of loops is starting to look just awful (bad flashbacks to my asp 3.0 days).
I looked into using the runtime serialization to json for my DTOs and then using a JQuery plugin for templated rendering of JSON. It seems like a "cool" idea, but is more of a programming exercise than I care to do at the moment.
How are people building more involved UIs with asp.net mvc?
If you're concerned about how your view markup mixed with code looks, you can try an alternate view engine:
Spark
NVelocity
Brail
NHaml
All of these view engines take different approaches to combining code and markup that can make your view markup "cleaner".
I've written some HtmlHelper extensions to help with table building. These extensions use a TagBuilder in code to generate the rows according to the values and HTMl attributes defined. The view code is considerably cleaner using these extension methods and the extension methods themselves are testable to ensure that they produce clean code reliably.
Sample view code:
<% var alternating = false;
foreach (var model in Model) { %>
<% using (Html.BeginTableRow( new { #class = alternating ? "alternating-row" : "" } )) { %>
<%= Html.TableElement( model.Column1 ) %>
<%= Html.TableElement( model.Column2, new { #class = 'some-class' } ); %>
<%= Html.TableElement( model.Column3 ) %>
<% }
alternating = !alternating;
%>
<% } %>
In addition, I've actually create a grid control that will generate a styled table using the above and most of my view code consists of rendering the grid control with the proper model.
<% Html.RenderPartial( "GridControl", Model, ViewData ); %>