Best practice for conditional output in ASP.NET MVC? - asp.net

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.

Related

Covert Razor delegate syntax to WebForms

I am trying to write this style of code from cassette using WebForms. Is this possible?
#{
var message = "Hello World!";
Bundles.AddInlineScript(
#<script>
if (someTest) {
alert('#message');
}
</script>);
}
I haven't managed to find an example of using methods with the Func<Object, Object> parameter in WebForms. Or is this because this only allowed by the Razor view engine?
<% Bundles.AddInlineScript("if (someTest) { ...") %>

write a string contain html tag on the page to create a html table in asp.net mvc

I use this code to return an string from my action :
public ActionResult Index()
{
string List = "";
List = "<table><tr><td>Ali</td></tr></table>";
ViewData["List"] = List;
return View();
}
and this is my view :
<body>
<%: ViewData["List"] %>
</body>
but instead to create a table when i browse the page , i see that the string "<table><tr><td>Ali</td></tr></table>" wrote on it. I use the firebug and see its html code . but i saw something like this :
<table><tr><td>Ali</td></tr></table>
Is there any body out there to help me?
Thansk
Regards
This is because you use the HtmlEncode tag
Change the <%: to <%=
will be come
<body>
<%= ViewData["List"] %>
</body>
and do not forget to HtmlEncode your data only to avoid any injection.

Dynamically add items to a collection in MVC2 using EditorFor()

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.

JavaScript action result no longer working after converting to partial view

Early yesterday, the following validation notice was working correctly. Then we converted the Index view where the request for this action originates to use a partial view, and the Delete ActionLink is now inside that partial view, and now the string argument to the JavaScript method call is rendered literally and as the only content on the 'destination' Delete view.
public ActionResult Delete(int id)
{
var perm = JobCardService.CheckBusinessRules(id);
if (!string.IsNullOrEmpty(perm))
{
return JavaScript("NotifyFailure('You may not delete this Installation: " + perm + "', false, 2000);");
}
JobCardViewData viewData = ViewDataFactory.CreateBaseViewData<JobCardViewData>("Installation List");
return View("Delete", viewData);
}
The Filter action returns the partial view, and is requested as below:
<div class="editor-field">
<% using (Ajax.BeginForm("Filter", "JobCard", new AjaxOptions { UpdateTargetId = "jobList" }))
{ %>
<%= Html.DropDownListFor(model => model.RequesterId, new SelectList(Model.RequesterList, "RequesterID", "CompanyName", Model.RequesterId), new { onchange = "$('#Select_Save').click();" })%>
<input id="Select_Save" type="submit" value="Save" style="display: none" />
<%
}%>
</div>
If the action method is responsible for returning a view, seems like the response shouldn't be returning a JavaScript if in error because no underlying ASP.NET page would be served, which means that you would see it as literal text.
Consider assigning the method call to ViewData, and in your client do something like:
<% if (ViewData["X"] != null) { %>
<script type="text/javascript">
<%= ViewData["X"] %>
</script>
<% } %>
Calling VIewData["X"] like I do should render the JavaScript code directly and get directly executed when parsed.
I think that might work; you can always utilize other mechanisms like eval to parse content, or do whatever else you might need....
Refer to the comment of this question ASP.NET MVC Javascript ActionResult
The other aspect is that using this return type is considered to be an anti-pattern and should be avoided. The suggested approach is to use a Json result.
Working example for JavaScriptResult in asp.net mvc
http://devlicio.us/blogs/billy_mccafferty/archive/2009/02/07/beware-of-asp-net-mvc-javascriptresult.aspx
Edit:
Since javascript is being returned from the Controller, an alternative would be to send script back to the browser that redirects the user to the correct page.
public ActionResult Delete(int id)
{
var perm = JobCardService.CheckBusinessRules(id);
if (!string.IsNullOrEmpty(perm))
{
return JavaScript("NotifyFailure('You may not delete this Installation: " + perm + "', false, 2000);");
}
// you may need to do a bit more to create a URL in the form of http://...
UrlHelper u = new UrlHelper(this.ControllerContext.RequestContext);
string url = u.Action("ActionName","ControllerName", new{id=1}); // the new Action will return the delete view
return Javascript(String.Format("window.location =""{0}"",url);
}
Refer to Creating a URL in the controller .NET MVC for more on the UrlHelper.
This may not be the best way to do this, but every other answer I have come across has required extensive rework to achieve. This requires one small, simple change and works exactly as required. All I had to do was change the Delete action link from this:
<%= Html.ActionLink("Delete", "Delete", new { id = item.InstallationDBNumber }) %>
to this:
<%= Ajax.ActionLink("Delete", "Delete", new { id = item.InstallationDBNumber }, new AjaxOptions { HttpMethod = "Get" }) %>

How to extend the ValidationSummary HTML Helper in ASP.NET MVC?

I need to wrap the Validation Summary in a div. How do I set the Validation Summary to wrap it with a div when errors are present?
<div class="validation-summary">
<%= Html.ValidationSummary("Login was unsuccessful. Please correct the errors and try again.") %>
</div>
I had to extend the validation summary extensions in another project of mine to deal with more than one form on a page.
Although this is different, you could create your own extension method...
namespace System.Web.Mvc
{
public static class ViewExtensions
{
public static string MyValidationSummary(this HtmlHelper html, string validationMessage)
{
if (!html.ViewData.ModelState.IsValid)
{
return "<div class=\"validation-summary\">" + html.ValidationSummary(validationMessage) + "</div>"
}
return "";
}
}
}
Then just call
<%= Html.MyValidationSummary(
"Login was unsuccessful. Please correct the errors and try again.") %>
HTHs,
Charles
What you can do is this :
<%if (!ViewData.ModelState.IsValid) { %>
<div class="validation-summary">
<%= Html.ValidationSummary(
"Login was unsuccessful. Please correct the errors and try again.") %>
</div>
<% } %>
For MVC 2, ValidationSummary is a extension method, you must add
using System.Web.Mvc.Html;
Use this CSS for li tag for example...
.validation-summary-errors ul li {color:Red;}

Resources