Reputation: 2104
I´m needing some help. I have the following scenario and I think that I doing something wrong.
- Model "State"
namespace App.Model
{
public class State
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int idState { get; set; }
[Required(ErrorMessage = "Initials is required")]
public string StateInitials { get; set; }
[Required(ErrorMessage = "Name is required")]
public string StateName { get; set; }
[Display(Name = "Update Date")]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime? UpdateDate { get; set; }
[Display(Name = "Update Responsible")]
public string UpdateResponsible { get; set; }
} //class
} //namespace
- Model "Location"
namespace App.Model
{
public class Location
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int idLocation { get; set; }
public int idState { get; set; }
[Required(ErrorMessage = "Name is required")]
public string LocationName { get; set; }
public string Status { get; set; }
public string ManagerName { get; set; }
public string Address { get; set; }
[Display(Name = "Update Date")]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime? UpdateDate { get; set; }
[Display(Name = "Update Responsible")]
public string UpdateResponsible { get; set; }
} //class
} //namespace
The relation between State and Location is one to many, but I didn´t describe this on model (using navigation fields).
I have a view where I want to edit the locations. To do that, I´m using the following view model.
- View Model "LocationsViewModel"
namespace App.ViewModel
{
public class LocationsViewModel
{
public State objState { get; set; }
public List<Location> lstLocations { get; set; }
} //class
} //namespace
To edit the Locations I use the following controller.
namespace App.Controllers
{
public class LocationController : Controller
{
private DbContext db = new DbContext();
// GET: /Location/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
State objState = db.States.Find(id);
if (objState == null)
{
return HttpNotFound();
}
LocationsViewModel model = new LocationsViewModel();
model.objState = objState;
model.lstLocations = getLocations(objState.idState); //I didn´t show this method here just to simplify
return View(model);
} //Edit
// POST: /Location/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Editar(LocationsViewModel model)
{
State objState = db.States.Find(model.objState.idState);
try
{
if (ModelState.IsValid)
{
//Saving Locations
foreach (Location obj in model.lstLocations)
{
Location objLocation = db.Locations.Find(obj.idLocation);
objLocation.LocationName = obj.LocationName;
objLocation.Status = obj.Status;
objLocation.ManagerName = obj.ManagerName;
objLocation.Address = obj.Address;
objLocation.UpdateDate = DateTime.Now;
objLocation.UpdateResponsible = User.Identity.Name;
db.Entry(objLocation).State = EntityState.Modified;
db.SaveChanges();
} //foreach
return RedirectToAction("Index");
}
}
catch (Exception e)
{
ModelState.AddModelError("", e.Message);
}
model.objState = objState;
model.lstLocations = getLocations(objState.idState); //I didn´t show this method here just to simplify
return View(model);
} //Edit
} //class
} //namespace
The problem/question is:
I wrote this code to edit (save) the list of locations of a specific State. When I submit the "Edit" view, the MVC try to validade the list of Locations (lstLocations) and the State (objState) as well, but I want to validate only the list of locations.
Note 1. I need to pass to my Edit view both objects: objState and lstLocations. I need the objState object because I show some State´s properties to the user on page (view).
Note 2. I´m getting ModelState.IsValid = false because model.objLocation is not valid, but I don´t want to check objLocation (is not relevant for this view). I just want to check the list of Locations (lstLocation)
What is the best approach to achieve my gol? Am I doing something wrong? Need I to change my way of thinking?
Upvotes: 0
Views: 2490
Reputation: 5847
In addition to the solution you've already chosen, I found the custom RequiredIfAttribute
useful. Using that, you can control if something is required base upon another condition, e.g.:
...
public bool RequireLocationName {
get {
return !Addresses.Any();
}
}
[RequiredIf("RequireLocationName", true)]
public bool LocationName { get; set; }
Upvotes: 0
Reputation: 748
You'll need two things. The first is to remove the object from the ModelState which you do not want to validate. The second is you need to put your code block that is to execute in a valid state within the if(ModelState.IsValid) block.
public ActionResult Edit(int? id)
{
//don't validate this field
ModelState.Remove("yourObject.property");
if (ModelState.IsValid)
{
...
}
}
Upvotes: 2