I'm trying to find out if there is a shorter way of writing data to a view than what I am currently doing. This is what I currently have in my view:
<td>
<%
if (Model.AnnualIncome != null)
{
%>
<%: "R " + Model.AnnualIncome.ToString() %>
<%
}
%>
</td>
Is there a shorter way of displaying annual income to the screen than having all the <% %>?
Thanks
Does this work?
<td>
<%: Model.AnnualIncome != null ? "R " + Model.AnnualIncome : string.Empty %>
</td>
How about using the ViewModel to format the data for the view?
public class AccountViewModel
{
public decimal AnnualIncome { get; set; }
public string GetAnnualIncome()
{
return Model.AnnualIncome != null ? "R" + AnnualIncome : string.Empty;
}
}
Then in your view, you can do something like:
<td><%= Model.GetAnnualIncome() %></td>
Something like <%=string.Format("R {0}", Model.AnnualIncome) %> should be more concise.
Edit: Oops, just realized that you don't want to print the "R" if it's null. In that case, something like this:
<%=(Model.AnnualIncome == null ? "" : string.Format("R {0}", Model.AnnualIncome)) %>
You could use another View Engine if you dont like <% %> everywhere.
Razor (CSHTML) isn't released yet but you can download a preview of it. I know there is also NHaml and another one as well.
The MVC team are working on a new ViewEngine called Razor, that would allow nicer syntax:
http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx
Related
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.
My company has a zero warning tolerance policy and I have a warning that I just can't get to go away. It is showing on the declaration of the string because
Warning 1 The variable 'message' is assigned but its value is never used
This is the code snippet:
<%
string message = "Message to be displayed";
if (Model.Count == 0)
{
%>
No records to display. <%= message %>
<%
}
else
{
%>
The rest of the code is correct, so it's not a syntax error.
Why would this kind of warning appear in the first place when I am clearly referencing it?
Thx in advance!
It's strange that your company has 0 tolerance to errors and still lets you write C# code in your views which turn them into spaghetti. Also you are hardcoding urls instead of using URL helpers which is very bad.
So you could start by slightly improving the code:
<% if (Model.Count == 0) { %>
No records to display.
<%= Html.ActionLink("Click here to add.", "Details", "ObjectDefinition") %>
<% else { %>
...
<% } %>
Change the declare as below, this issue will be fixed.
When you see this kind of warning, just review the declare. It will OK then.
<%
if (Model.Count == 0)
{
string message = "Message to be displayed"; // declare message here :)
%>
No records to display. <%= message %>
<%
}
else
{
%>
Best regards.
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'm ramping up on ASP.NET MVC and looking at how I output messages in the view. What's the best way to do something like this? Helpers? Controls? Or just as is?
<% if (ViewData.ContainsKey("message") && !string.IsNullOrEmpty(ViewData["message"].ToString())) { %>
<div class="notice">
<%= ViewData["message"] %>
</div>
<% } %>
I would use an html helper:
public static class HtmlExtensions
{
public static string GetMessage(this HtmlHelper htmlHelper)
{
var message = htmlHelper.ViewData["message"] as string;
if (string.IsNullOrEmpty(message))
{
return string.Empty;
}
var builder = new TagBuilder("div");
builder.AddCssClass("notice");
builder.SetInnerText(message);
return builder.ToString();
}
}
and in the view:
<%= Html.GetMessage() %>
Remark: don't forget to html encode the value of the message if you decide to use your code the way it is.
I think a condition like what you have is the simplest approach. A control feels a bit too "heavy" for this. Maybe a helper method if you find yourself repeating it a lot.
Today is the very first day I've ever even seen aspx, so, please bear with me...
Basically, I want to determine if a string is empty. If it is empty, then I don't want anything to output, if it's not, then I want to output the string itself.
<%= o_handler.renderDDesc()%> //This is the string itself... If this is empty, then I want I want nothing to print
I tried:
<%if (o_handler.renderDDesc().length() > 0) { %>
<%= o_handler.renderDDesc()%>
<%}%>
But, that didn't seem to do anything. I didn't get an error, but it also didn't appear?
<%
string desc = o_handler.renderDesc();
if (!String.IsNullOrEmpty(desc)) {
Response.Write(desc);
}
%>
<%= !String.IsNullOrEmpty(o_handler.renderDDesc()) ? o_handler.renderDDesc() : ""%>
I would simply use a ternary operator as follows:
<%=( o_Handler.IsNullOrEmpty() ? string.Empty : o_handler.renderDDesc() ); %>