How do I figure out which of the keys in ModelState that contains an error when ModelState.IsValid is false? Usually I would just hover the mouse thru the ModelState.Values list checking item by item for error count > 0. But now I'm working on a view that has some lists of complex objects, totalling 252 ModelState items(each item of each object of each list has an entry on ModelState.Keys).
So, is there an easier way to point out the error source?
You can check the ViewData.ModelState.Values collection and see what are the Errors.
[Httpost]
public ActionResult Create(User model)
{
if(ModelState.IsValid)
{
//Save and redirect
}
else
{
foreach (var modelStateVal in ViewData.ModelState.Values)
{
foreach (var error in modelStateVal.Errors)
{
var errorMessage = error.ErrorMessage;
var exception = error.Exception;
// You may log the errors if you want
}
}
}
return View(model);
}
}
If you really want the Keys(the property name), You can iterate through the ModelState.Keys
foreach (var modelStateKey in ViewData.ModelState.Keys)
{
var modelStateVal = ViewData.ModelState[modelStateKey];
foreach (var error in modelStateVal.Errors)
{
var key = modelStateKey;
var errorMessage = error.ErrorMessage;
var exception = error.Exception;
// You may log the errors if you want
}
}
ModelState.Values.SelectMany(v => v.Errors);
is considered cleaner.
where modelState is a ModelStateDictionary object
foreach (var keyModelStatePair in modelState)
{
var key = keyModelStatePair.Key;
var errors = keyModelStatePair.Value.Errors;
if (errors != null && errors.Count > 0)
{
var errorMessages = errors.Select(error =>
{
return error.ErrorMessage;
}).ToArray();
// do something with your keys and errorMessages here
}
}
I had the same problem for a long time and finally I found it. In my case, it was the Id field :)
Just place a breakpoint and check your ModelState in runtime and go to this section :
ModelState -> Root -> Children
and you will see all valid and invalid Keys
Related
I would like to ask for your help. I want to validate my delete request class. The rule is:
"Deletion allowed only for one element with the biggest price in
database for each type of product"
. repositoryEntities is not null but the Result is: Enumeration yielded no results.
Can you please check below code and let me know what is wrong?
private void CanIDelete(DeleteProductRequest entity, CustomContext context)
{
var repositoryEntities = _productRepository.Queryable.Where(s => s.TypeOfProductId.Equals(entity.TypeOfProductId) && !s.IsDeleted);
if (repositoryEntities != null)
{
var theBiggestPriceInDatabase = Decimal.MinValue;
foreach (var repositoryEntity in repositoryEntities)
{
if (theBiggestPriceInDatabase < repositoryEntity.Price)
{
theBiggestPriceInDatabase = repositoryEntity.Price;
continue;
}
if (entity.Price != theBiggestPriceInDatabase)
{
context.AddFailure("Deletion allowed only for one product 'with the biggest price' in database for each type of product");
return;
}
}
}
In C# windows application, I am comparing two different string arrays and depending on which array size is big, I add or delete items to a list view box. using the below code I am able to add to list view without any issues, but I am not able to remove from it.
I get an error that says.
"Error CS1503, Argument 1: cannot convert from 'string' to 'System.Windows.Forms.ListViewItem'"
Here is an excerpt from my code
string[] currentFilesList = GetFileList();
if (currentFilesList.Length > prevFilesList.Length)
{
var addedList = currentFilesList.Except(prevFilesList).ToArray();
foreach (var item in addedList)
{
listView1.Items.Add(item);
}
}
if (currentFilesList.Length < prevFilesList.Length)
{
var removedList = prevFilesList.Except(currentFilesList).ToArray();
foreach (string item in removedList)
{
listView1.Items.Remove(item); //I get error here on "item" Argument 1: cannot convert from 'string' to 'System.Windows.Forms.ListViewItem'"
}
}
prevFilesList = currentFilesList;
I tried both string and var but same result.
you can remove item by
foreach (string item in removedList)
{
var toRemove =listView1.Items.Find(item);
if (toRemove != null)
{
listView1.Items.Remove(toRemove);
}
}
or you can use RemoveByKey
foreach (string item in removedList)
{
listView1.Items.RemoveByKey(item);
}
You can try this by using linq
var newlist = listView1.Cast<ListViewItem>().Where(p=>p.Text.Contains("OBJECT")).ToList().ForEach(listBox1.Items.Remove);
So I'm in trouble with this error:
An unhandled exception of type 'System.Data.Entity.ModelConfiguration.ModelValidationException' occurred in EntityFramework.dll.
Here is the code:
public ActionResult SaveItems(string[] fooItems, int category_id)
{
foreach (item item in DB.items)
{
if (item.category_id == category_id)
{
if(item != null)
DB.items.Remove(item);
DB.SaveChanges();
}
}
}
I'm trying to remove an item from the database, and save changes after that, when I get this error.
Any help is appreciated.
Thanks!
As someone correctly mentioned in the comments, you cannot make changes to the underlying list while using a foreach loop. Change your action method to this:
public ActionResult SaveItems(string[] fooItems, int category_id)
{
var itemsToRemove = DB.items.Where(i => i.category_id == category_id).ToList();
DB.items.RemoveRange(itemsToRemove);
DB.SaveChanges();
}
You've got a couple issues:
You're modifying a list from within the foreach (as noted by Alex Krupka in a comment)
You're calling SaveChanges after every removal
This code loads each item one at a time, resulting in a lot of unnecessary calls to the DB
You're removing items from a method called "SaveItems"
I would use the following:
public ActionResult SaveItems(string[] fooItems, int category_id)
{
var itemsToRemove = DB.items.Where(e => e.category_id == category_id)
.ToList();
foreach (var item in itemsToRemove)
{
DB.items.Remove(item);
}
DB.SaveChanges();
}
I am trying to loop through data that is passed to my view in a model object. I want to list out the property name and the property value of each of the model properties, even if they are null. I have been at this for a few hours and have tried googling it but cannot get any good examples that work.
I got this to list out all of the properties of the current object, however cannot get the values:
#model List<object>
#foreach (var obj in Model)
{
var properties = obj.GetType().GetProperties();
foreach (var property in properties)
{
string name = null;
var value = ""
try
{
name = property.Name;
value = property.GetType().GetProperty(property.Name).GetValue(property, null).ToString();
}
catch (Exception e)
{
<p>#e</p>
}
finally
{
<p>#name - #value</p>
}
}
And the controller code:
RootobjectPlayerData obj = JsonConvert.DeserializeObject<RootobjectPlayerData>(jsonstring);
List<object> list = new List<object>();
list.Add(obj.data.accountinfo);
list.Add(obj.data.accountinfo.statistics);
list.Add(obj.data.accountinfo.statistics.clan);
list.Add(obj.data.accountinfo.statistics.company);
list.Add(obj.data.accountinfo.statistics.all);
list.Add(obj.data.accountinfo.statistics.historical);
list.Add(obj.data.accountinfo.statistics.team);
return View(list);
I am able to do a break point and view all of the data within each of the objects, however I cannot get it to print out on screen.
First of all you are getting the property value incorrectly. You should get the value from the object you have, but not from the type of the property:
value = obj.GetType().GetProperty(property.Name).GetValue(obj, null)
Secondly, try to loop only through data that's not null:
#foreach (var obj in Model.Where(w => w != null))
Try getting the values from i, not x.
try
{
name = x.Name;
// Wrong
// value = x.GetType().GetProperty(x.Name).GetValue(x, null).ToString();
// Correct
value = x.GetValue(i, null).ToString();
}
catch (Exception e)
{
<p>#e</p>
}
I need confirmation of my approach for this, I'm using EF and ASP.NET MVC and I'm trying to remove entities based on user selection (i.e based on what they have checked/unchecked).
To do this I'm looking at the Ids that are passed from the form from the checkboxes, matching what I have in the database and then first adding any which are new and then removing any which don't match.
Following is the code that I originally had:
[HttpPost]
public ActionResult Edit(int id, FormCollection collection, VMinstanceRole vmodel)
{
try
{
var instancerole = db.instanceRoles.Find(id);
if (ModelState.IsValid)
{
UpdateModel<instanceRole>(instancerole, "instanceRole");
var keys = instancerole.rights.Select( c => c.Id);
foreach (var pid in vmodel.selectedId.Except(keys))
{
var right = new right { Id = pid };
db.rights.Attach(right);
instancerole.rights.Add(right);
}
foreach (var pid in keys.Except(vmodel.selectedId))
{
var right = instancerole.rights.Where(c => c.Id == pid).Single();
instancerole.rights.Remove(right);
}
db.SaveChanges();
}
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch (InvalidCastException e)
{
return View();
}
}
However, the following error was presented "Collection was modified; enumeration operation may not execute."
So to try and resolve this I decided to keep a seperate list and remove it based on teh list afterwards to overcome the error:
[HttpPost]
public ActionResult Edit(int id, FormCollection collection, VMinstanceRole vmodel)
{
try
{
var instancerole = db.instanceRoles.Find(id);
List<right> removeList = new List<right>();
if (ModelState.IsValid)
{
UpdateModel<instanceRole>(instancerole, "instanceRole");
var keys = instancerole.rights.Select( c => c.Id);
foreach (var pid in vmodel.selectedId.Except(keys))
{
var right = new right { Id = pid };
db.rights.Attach(right);
instancerole.rights.Add(right);
}
foreach (var pid in keys.Except(vmodel.selectedId))
{
var right = instancerole.rights.Where(c => c.Id == pid).Single();
removeList.Add(right);
}
foreach (var right in removeList)
{
instancerole.rights.Remove(right);
}
db.SaveChanges();
}
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch (InvalidCastException e)
{
return View();
}
}
This seems to work, however, I'm not sure whether I've done the right thing. Mainly becuase I'm doing another loop. Is there a better way to approach this or is this good enough ?
You found one standard solution. The other solution that works would be to call ToList on the LINQ operation that produces your keys object: doing so would disconnect keys from instanceroles collection, allowing for arbitrary independent modifications on the original collection.
Try this:
foreach (var pid in keys.Except(vmodel.selectedId).ToList())
{
var right = instancerole.rights.Where(c => c.Id == pid).Single();
instancerole.rights.Remove(right);
}
Enumerator you enumerate in foreach loop will be already disposed by the moment you delete your first item.
The reason for not being able to edit a collection when enumerating with foreach is well enough documented here alone (just check the 'related' links to the side), and in knowing you can't do that, you could use a simple for loop and amend to index upon removal of an item - this allows you to maintain one loop.
for (int i = 0; i < max; i++) {
//if removing an item
//manipulate the index as desired...
i--;
}