How do I get the collection of Model State Errors in ASP.NET MVC? - html

How do I get the collection of errors in a view?
I don't want to use the Html Helper Validation Summary or Validation Message. Instead I want to check for errors and if any display them in specific format. Also on the input controls I want to check for a specific property error and add a class to the input.
P.S. I'm using the Spark View Engine but the idea should be the same.
So I figured I could do something like...
<if condition="${ModelState.Errors.Count > 0}">
DisplayErrorSummary()
</if>
....and also...
<input type="text" value="${Model.Name}"
class="?{ModelState.Errors["Name"] != string.empty} error" />
....
Or something like that.
UPDATE
My final solution looked like this:
<input type="text" value="${ViewData.Model.Name}"
class="text error?{!ViewData.ModelState.IsValid &&
ViewData.ModelState["Name"].Errors.Count() > 0}"
id="Name" name="Name" />
This only adds the error css class if this property has an error.

<% ViewData.ModelState.IsValid %>
or
<% ViewData.ModelState.Values.Any(x => x.Errors.Count >= 1) %>
and for a specific property...
<% ViewData.ModelState["Property"].Errors %> // Note this returns a collection

To just get the errors from the ModelState, use this Linq:
var modelStateErrors = this.ModelState.Keys.SelectMany(key => this.ModelState[key].Errors);

Condensed version of #ChrisMcKenzie's answer:
var modelStateErrors = this.ModelState.Values.SelectMany(m => m.Errors);

This will give you one string with all the errors with comma separating
string validationErrors = string.Join(",",
ModelState.Values.Where(E => E.Errors.Count > 0)
.SelectMany(E => E.Errors)
.Select(E => E.ErrorMessage)
.ToArray());

Putting together several answers from above, this is what I ended up using:
var validationErrors = ModelState.Values.Where(E => E.Errors.Count > 0)
.SelectMany(E => E.Errors)
.Select(E => E.ErrorMessage)
.ToList();
validationErrors ends up being a List<string> that contains each error message. From there, it's easy to do what you want with that list.

Thanks Chad! To show all the errors associated with the key, here's what I came up with. For some reason the base Html.ValidationMessage helper only shows the first error associated with the key.
<%= Html.ShowAllErrors(mykey) %>
HtmlHelper:
public static String ShowAllErrors(this HtmlHelper helper, String key) {
StringBuilder sb = new StringBuilder();
if (helper.ViewData.ModelState[key] != null) {
foreach (var e in helper.ViewData.ModelState[key].Errors) {
TagBuilder div = new TagBuilder("div");
div.MergeAttribute("class", "field-validation-error");
div.SetInnerText(e.ErrorMessage);
sb.Append(div.ToString());
}
}
return sb.ToString();
}

Here is the VB.
Dim validationErrors As String = String.Join(",", ModelState.Values.Where(Function(E) E.Errors.Count > 0).SelectMany(Function(E) E.Errors).[Select](Function(E) E.ErrorMessage).ToArray())

If you don't know what property caused the error, you can, using reflection, loop over all properties:
public static String ShowAllErrors<T>(this HtmlHelper helper) {
StringBuilder sb = new StringBuilder();
Type myType = typeof(T);
PropertyInfo[] propInfo = myType.GetProperties();
foreach (PropertyInfo prop in propInfo) {
foreach (var e in helper.ViewData.ModelState[prop.Name].Errors) {
TagBuilder div = new TagBuilder("div");
div.MergeAttribute("class", "field-validation-error");
div.SetInnerText(e.ErrorMessage);
sb.Append(div.ToString());
}
}
return sb.ToString();
}
Where T is the type of your "ViewModel".

Got this from BrockAllen's answer that worked for me, it displays the keys that have errors:
var errors =
from item in ModelState
where item.Value.Errors.Count > 0
select item.Key;
var keys = errors.ToArray();
Source: https://forums.asp.net/t/1805163.aspx?Get+the+Key+value+of+the+Model+error

Related

Pass data from a query to a view

The problem I have is that I do not know how I can use the data of a query in a view if someone can give me a serious idea, the form I use is this but it gives me an error:
My Controller:
public function edit($id){
$datosProfesor = DB::table('profesor')->where('id', $id)->get();
$institucionDB = DB::table('institucion')->get();
$datos = array('datosProfesor' => $datosProfesor, 'institucionDB' => $institucionDB);
return view('profesorView/editarProfesor', $datos);
}
My view:
<div class="form-group">
<h4>Nombre</h4>
<input type="text" name="nombre_profesor" id="nombre_profesor" class="form-control" placeholder= 'Nombre' value="{{$datosProfesor['id']}}">
</div>
The error that appears to me is this:
Undefined index: id (View: /var/www/html/Konecte/resources/views/profesorView/editarProfesor.blade.php)
The get() method returns an Illuminate\Support\Collection containing the results where each result is an instance of the PHP StdClass object. You may access each column's value by accessing the column as a property of the object:
foreach ($datosProfesor as $profesor) {
echo $profesor->id;
}
If you want to get a single result then you can use find() method as:
$datosProfesor = DB::table('profesor')->find($id);
which is a short form of:
$datosProfesor = DB::table('profesor')->where('id', $id)->first();
Just one more tip for you that you can use PHP's compact() method for creating array containing variables and their values. So that you can get rid of line
$datos = array('datosProfesor' => $datosProfesor, 'institucionDB' => $institucionDB);
Your final code will look as:
public function edit($id){
$datosProfesor = DB::table('profesor')->find($id);
$institucionDB = DB::table('institucion')->get();
return view('profesorView/editarProfesor', compact('datosProfesor', 'institucionDB'));
}

how to bind dropdownlist in view dynamically ? mvc4

I want to replace this code in my view
Code :
<label for="name">Lead Source</label><select name="Lead_Source" id="Lead_Source" rel="2">
<option value="1">News Papers </option>
<option value="2">Internet</option>
<option value="3">Social networking</option>
<option value="4">Others</option>
</select>
I want to replace with Dropdownlist so I will bind data dynamically by I am getting undone by work .
I tried like this:
<label for="name">Lead Source</label> #Html.DropDownListFor(c=>c.Lead_Source, Model.Lead_Source_List,"--Select Source--");
The error i am getting after i replace static code is
CS1928: 'System.Web.Mvc.HtmlHelper<Ibs.Iportal.Iwise.Web.Models.LeadSortModel>' does not contain a definition for 'DropDownListFor' and the best extension method overload 'System.Web.Mvc.Html.SelectExtensions.DropDownListFor<TModel,TProperty>(System.Web.Mvc.HtmlHelper<TModel>, System.Linq.Expressions.Expression<System.Func<TModel,TProperty>>, System.Collections.Generic.IEnumerable<System.Web.Mvc.SelectListItem>, object)' has some invalid arguments
EDIT : I am passing a model to view which contain a Lead_Source_List of enumerable list data
Regards
you should create a view model and make strongly typed view,do something like this in you action:
public ActionResult YourAction(int id)
{
var model = new MyViewModel();
using (var db = new SomeDataContext())
{
// Get the boxer you would like to edit from the database
model.Boxer = db.Boxers.Single(x => x.BoxerId == id);
// Here you are selecting all the available weight categroies
// from the database and projecting them to the IEnumerable<SelectListItem>
model.WeightCategories = db.WeightCategories.ToList().Select(x => new SelectListItem
{
Value = x.WeightCategoryId.ToString(),
Text = x.Name
})
}
return View(model);
}
this chunk is populating select list item:
model.WeightCategories = db.WeightCategories.ToList().Select(x => new SelectListItem
{
Value = x.WeightCategoryId.ToString(),
Text = x.Name
})
and assigned to model
Now use in view this way:
#model MyViewModel
#Html.DropDownListFor(
x => model.Boxer.CurrentWeightCategory.WeightCategoryId,
Model.WeightCategories
)

Get Value from object in html MVC

How I can get an object in HTML?
I have this:
#Html.DisplayFor(model => model.Product.Keys.Where(x => x.TransactionID == model.TransactionID))
but here I have an object, and I want to display only one value.
I tried something like this:
#{
var key = model.Product.Keys.Where(x => x.TransactionID == model.TransactionID);
}
but model name doesn't exist in the current context.
Any ideas?
You should to use Model
#{
var key = Model.Product.Keys.Where(x => x.TransactionID == Model.TransactionID);
}

ASP.Net MVC SelectList not 'Selecting' Correct Item

I have been asked to look at a bug in some ASP.Net MVC code and have a (to me) very odd problem with a SelectList.
The code from the controller to generate the items (a method to return a SelectList, there are 5 in total). Each SelectList is then saved into the ViewData collection.
List<SelectListItem> items = new List<SelectListItem>();
string yesText = "Yes";
string noText = "No";
if (ci.LCID.Equals((int)LanguageCodes.FRANCE))
{
yesText = "Oui";
noText = "Non";
}
SelectListItem yesItem = new SelectListItem();
yesItem.Text = yesText;
yesItem.Value = ((int)MarketingBy.Yes).ToString();
yesItem.Selected = selectedValue != null && selectedValue.Equals(int.Parse(yesItem.Value));
SelectListItem noItem = new SelectListItem();
noItem.Text = noText;
noItem.Value = ((int)MarketingBy.No).ToString();
noItem.Selected = selectedValue != null && selectedValue.Equals(int.Parse(noItem.Value));
items.Add(yesItem);
items.Add(noItem);
return new SelectList(items, "Value", "Text", yesItem.Selected ? yesItem.Value : noItem.Value);
A quick 'quickwatch' at the point of creation suggests everything is ok:
At the point the view is being rendered, the values still look ok. However when the view loads, the first item in the list is always selected. The HTML generated is:
<tr>
<td>Fax</td>
<td>
<select id="MarketingByFax" name="MarketingByFax">
<option value="134300002">Yes</option>
<option value="134300001">No</option>
</select>
</td>
</tr>
(Other values ommitted for clarity).
Any ideas? Or avenues to research? The author is adamant that this was working 'up til last week' (I have no idea either way).
Edit: Code for the view -
<td><%: Html.DropDownList("MarketingByFax", (SelectList)ViewData["MarketingByFaxList"])%></td>
This code looks just horrible in every imaginable aspect (IMHO of course). I have no idea why it doesn't work and I don't want to know. All I can do is to suggest you how to improve it (so you can stop reading this post if you are looking for a solution about why your code doesn't work as I have no freaking idea).
So the first improvement would be to get rid of any ViewData and introduce a view model:
public class MyViewModel
{
public string SelectedValue { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
}
then I would have a controller action that would populate this view model:
public ActionResult Index()
{
var model = new MyViewModel
{
// I want to preselect the second value
SelectedValue = "No",
Items = new[]
{
new SelectListItem { Value = "Yes", Text = "yeap !" },
new SelectListItem { Value = "No", Text = "nope !" },
}
};
return View(model);
}
and in my strongly typed view I would simply bind the helper to the view model:
<%= Html.DropDownListFor(
x => x.SelectedValue,
new SelectList(Model.Items, "Value", "Text")
) %>
Also if you want to work with some enum types you may find the following extension method useful.
See how easy it is? No more ugly casts with ViewData, no more need to define any lists and specify some complicated conditions, ...
Remark: once again, those are just my 2ยข, you can continue the combat with ViewData if you will.
you can try
<%: Html.DropDownList("MarketingByFax", (IEnumerable<SelectListItem>)ViewData["MarketingByFaxList"])%>
dropdwon has an overload that accepts the enumeration of Selectlist type objects and it sets the value of list automatically depending upon Selected property of selectListItems in the list. for this you have to set
ViewData["MarketingByFaxList"] = items;//where item is IEnumerable<SelectListItem> or List<SelectListItem> as you used in your code

MVC2: Is there an Html Helper for raw Html?

Is there an Html helper that simply accepts and returns raw html? Rather than do something ugly like this:
<% if (Model.Results.Count > 0) { %><h2>Results</h2><% } %>
I'd like to do something like this:
<% if (Model.Results.Count > 0) { Html.RawHtml("<h2>Results</h2>") } %>
Not a whole lot cleaner, but I think it's a bit of an improvement. Does something like that exist? Or is there perhaps a better alternative to output raw html from within those escape characters than using Html helpers?
For MVC2:
<%: MvcHtmlString.Create("<h2>Results</h2>") %>
Found here:
store and display html tags in MVC
Response.Write should work. (Although maybe it's kind of taking a step back!) You should be able to create an extension method to do it. And maybe instead of using HTML string, you might want to build your markup in code using the TagBuilder.
There is such helper now:
Html.Raw("<h2>Results</h2>")
If you want to use an HtmlHelper for whatever you're doing, you can return an MvcHtmlString built with a TabBuilder
Here an example of one that I use:
public static MvcHtmlString AccountsDropDown(this HtmlHelper helper, string name, object htmlAddributes = null, bool addNull = false, Guid? selected = null)
{
Account acc = HttpContext.Current.Session["account"] as Account;
TagBuilder tb = new TagBuilder("select");
tb.GenerateId(name);
tb.Attributes["name"] = name;
if (addNull)
tb.InnerHtml += string.Format("<option value= '{0}'> {1} </option>", "", "None");
Dictionary<Guid, String> accounts;
if (acc.Master)
accounts = db.Account.ToDictionary(x => x.Id, x => x.Name);
else
accounts = db.Account.Where(x => x.Id == acc.Id).ToDictionary(x => x.Id, x => x.Name);
foreach (var account in accounts)
tb.InnerHtml += string.Format(
"<option value= '{0}' {2}> {1} </option>",
account.Key,
account.Value,
selected == account.Key ? " selected='selected' " : ""
);
return new MvcHtmlString(tb.ToString());
}