Get Autogenerated Guid- MVC - asp.net-mvc

Does anyone happen to know if there is a way in the Entity Framework to return me the Guid of a just inserted row, assume the column is an guid which is auto Generated.
I am using MVC with Entity Framework. I am using Repository Method ADD(), the return type of the method is void.
Any one knows?

StewieFG,
On adding the item, and hitting SaveChanges(), your object should now be populated with the value of the autogenrated column. Consider the example below:
[HttpPost]
public ActionResult Create(MyEditViewModel viewModel)
{
if (ModelState.IsValid) {
_myService.Insert(viewModel.Entity);
_myService.SaveChanges();
// we can query the column value for the autogenerated value now
// i.e. viewModel.Entity.GuidIDColumn value etc..
return this.RedirectToAction(x => x.Index());
} else {
PopulateViewModel(viewModel);
return View(viewModel);
}
}
hope this helps

Related

MVC 4 validation NullReferenceException when returning to view null model data

In my controller, I'm fetching some data to fill a combobox in the view. When data is posted, I check for
ModelState.IsValid
property, if it doesn't, I need to return to the view to show validations messages errors. However, the model only contains the posted data and the other needed to load the combobox is null and it throws a NullReferenceException. Which is the right way to solve this?
public ActionResult Index(){
CourtBussines courtBussines = new CourtBussines();
IList<Court> courts = new List<Court>();
courts.AddRange(courtBussines.GetCourtsOpenedList());
CourtSelectionModel courtSelectionModel = new CourtSelectionModel{Courts = courts, SelectedCourtId = -1};
return View(courtSelectionModel);
}
[Authorize]
[HttpPost]
public ActionResult Index(CourtSelectionModel courtSelectionModel){
if (!ModelState.IsValid){
return View(courtSelectionModel); //Here, the data to load combobox is null and fails.
}
return RedirectToAction("Horarios", courtSelectionModel);
}
You would have to re-initialize the Courts list, as the entire list is not posted.
Try something like.
[Authorize]
[HttpPost]
public ActionResult Index(CourtSelectionModel courtSelectionModel){
if (!ModelState.IsValid){
IList<Court> courts = new List<Court>();
courts.AddRange(courtBussines.GetCourtsOpenedList());
courtSelectionModel.Courts = Courts;
courtSelectionModel.SelectedCourtId = -1;
return View(courtSelectionModel); //Here, the data to load combobox is null and fails.
}
return RedirectToAction("Horarios", courtSelectionModel);
}

Prevent ModelState.IsValid from validating attached entities?

Is there a way to override ModelState.IsValid?
Some of the entities to be validated are just attached entities, so all the fields except the ID are not to be validate as the entity is in state Unchanged.
Is there a way to do this?
Has anyone faced this issue before?
Update
Say I have the following action:
[HttpPost]
public ActionResult SaveEntity(MyEntity entity)
{
var isValid = ModelState.IsValid; //false
}
Since the model validates all properties and all descendant properties of entity, there has to be a way to check on each entity of those descendants, whether it's attached to the context, and if it is, remove error from ModelState, something like the following:
public ActionResult TryValidateDetachedModel(MyEntity entity, DbContext context)
{
foreach (var ms in ModelState.Where(ms => ms.Value.Errors.Any()).ToArray())
// should iterate over something like GetAllEntityTypesMetadata()
{
var entity = GetEntityFromMetadata(ms);
if (context.Entry(entity).State == EntityState.Unchanged)
{
ms.Value.Errors.Clear();
}
}
}
What I'm trying to do in the above pseudo code is to check the entities in the validation chain, and if one of them is attached as Unchanged, skip validation / remove its errors.
Right now I have to do it hard-coded manually by checking ModelState.Key, I'm looking for a more generic and efficient way.
To clear all errors use next
ModelState.Clear();
regards
Here's what I do to ensure the validation only applies to the current entity:
foreach (var key in ModelState.Keys)
if (key.Split('.').Length > 2)
ModelState[key].Errors.Clear();
if (!ModelState.IsValid)
return BadRequest(ModelState);
The check for the occurrences of . means: if the modelstate key is something like currentDTO.relatedDTO.field then that validation error is ignored (cleared). If it's just id or currentDTO.validateThisField, then it doesn't get cleared.

Relationship field is not updated in Edit action (ASP.NET, EF5)

I would really appreciate some insight on this: The following code
[HttpPost]
public ActionResult Edit(BeamCollection beamcollection)
{
if (ModelState.IsValid)
{
beamcollection.BeamMaterial = db.Types.Find(Convert.ToInt32(Request.Form.Get("BeamMaterial_ID")));
db.Entry(beamcollection).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Details", "Bridge");
}
return View(beamcollection);
}
When I attempt to modify a BeamCollection record, all changes are reflected and saved to the DB except for the beamcollection.BeamMaterial which takes the selected value from a DropDownList. When I debug, I can see that the selected value is being assigned to beamcollection.BeamMaterial!
By the way, this field is defined as follows
public virtual AllTypes BeamMaterial { get; set; }
So it reflects a one to many relationship with AllTypes, but it is a unidirectional relationship.
What is kind of strange (to me), is the the same technique is used for the Create action and it perfectly works:
public ActionResult Create(BeamCollection beamcollection)
{
if (ModelState.IsValid)
{
beamcollection.BridgeInfo = db.Bridges.Find(bridgeID);
beamcollection.BeamMaterial = db.Types.Find(Convert.ToInt32(Request.Form.Get("BeamMaterial_ID")));
db.BeamCollections.Add(beamcollection);
db.SaveChanges();
return RedirectToAction("Details", "Bridge");
}
return View(beamcollection);
}
Why is this happening and how to make it work, Please help.
try to use:
db.attach(beamcollection.GetType().Name,beamcollection);
db.ObjectStateManager.ChangeObjectState(beamcollection, EntityState.Modified);
db.SaveChanges();
Thanks to Fabrice's tip I managed to find the correct way, Here is the code:
var currentBeamCollection = db.BeamCollections.Find(beamcollection.ID);
db.Entry(currentBeamCollection).CurrentValues.SetValues(beamcollection);
currentBeamCollection.BeamMaterial = beamcollection.BeamMaterial;
db.SaveChanges();
The logic is as follows: get the original record, update all fields (except for the navigation properties, read below), update the navigation property, finally save.
When I tried to do the following
db.Entry(currentBeamCollection).CurrentValues.SetValues(beamcollection.BeamMaterial);
The system failed with an exception that complains about setting the ID property. I also read that CurrentValues.SetValues() doesn't update navigation properties, and I noticed that the BeamMaterial property was not being updated, so I needed to update it manually.
Thanks Fabrice.

How to pass thw Viewdata to all the views in my controller?

i have a dropdown list which select a value
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Screenname(FormCollection collection)
{
Viewdata["screenname"] = collection[0];
return RedirectToAction("Index", new { ScreenName = ViewData["screenname"] });
}
then i want to access this ViewData in other actions like this
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection collection, string screenname)
{
try
{
/// thats my dataobject which creates
DataObj.SaveData(Guid.Empty, collection, screenname);
return RedirectToAction("Index", new { ScreenName = ViewData["screenname"] });
}
catch
{
return View("Error");
}
}
where index looks like this ...
public ActionResult Index(string ScreenName)
{
///thats my list
GetTable = new GetDataTable(ScreenName);
return View(GetTable);
}
First when i select the value and index gets executed properly.... but when i try to access the viewdata again it doesn't contain the value so anybody if please can help ...
or alternate method to save and retrieve data .
The ViewData object is specific for the particular action that is executing. To pass data between actions, use TempData. more on the difference between the two on MSDN.
You can also directly write to the session state through the Controller.Session property.
This has actually been covered quite often here. The solution for now is to use TempData to save the data you need before you use RedirectToAction().
If you do a search for "RedirectToAction" you'll find a number of posts covering this topic, such as this one.
The next official release of the framework will fix this.
I used a view to take the data from the user and then saved it to a static variable and then used this variable to pass the data to all the other views .
Thanks anyways

Update a row in ASP.NET and MVC LINQ to SQL

I have a simple row that has 4 columns:
{ [Primary Key Int]RowID, [text]Title, [text]Text, [datetime]Date }
I would like to allow the user to edit this row on a simple page that has a form with the fields "Title" and "Text".
There is a hidden field to store the RowID.
When the user posts this form to my controller action, I want it to update the row's Title and Text, and keep the Date the same. I don't want to have to explicitly include a hidden field for the Date in the form page.
Here is my action:
[AcceptVerbs(HttpVerb.Post)]
public ActionResult EditRow(Row myRow)
{
RowRepository.SaveRow(myRow)
return View("Success");
}
RowRepository:
public void SaveRow(Row myRow)
{
db.MyRows.Attach(myRow);
db.Refresh(RefreshMode.KeepCurrentValues, myRow);
db.SubmitChanges();
}
This dosen't keep the "Date" value already in the row and tries to insert a value that throws an timespan exception.
How can I just tell it to keep the old values?
I tried doing RefreshMode.KeepChanges and nothing.
I'm not in a position to test this at the moment but try making the datetime column nullable and then ensure that the datetime passed into SaveRow has a null value.
Try
[AcceptVerbs(HttpVerb.Post)]
public ActionResult EditRow([Bind(Exclude="Date")] Row myRow) {
RowRepository.SaveRow(myRow)
return View("Success");
}
Update
Try this approach, where there is no 'Date' field on your page
[AcceptVerbs(HttpVerb.Post)]
public ActionResult EditRow(int RowID) {
Row myRow = RowRepository.GetRow(RowID);
UpdateModel(myRow);
RowRepository.Save();
return View("Success");
}
In your repository
public void Save() {
db.SubmitChanges();
}
This will only save the changes made to 'myRow'
You will have add a method in the partial class / override the code it build.
The class Table does implement "INotifyPropertyChanging|ed" which is used to track which column has been changed.
You can hack it and reset the value "this.PropertyChanged".
But what I do at work is a stupid READ-APPLY-WRITE approach (and I am using WebForm).
public void SaveRow(Row myRow)
{
var obj=db.MyRows.Where(c=>c.id==myRow.id).First();
obj.a=myRow.a;
obj.b=myRow.b;
db.SubmitChanges();
}
You can do a bit simpler.
public void SaveRow(Row myRow)
{
db.MyRows.Attach(new Row(){
Id=myRow.Id,
Title=myRow.Title,
Text=myRow.Text,
});
db.SubmitChanges();
}
PS. I am new to LINQ to SQL. Please let me know if there is a smarter way to do it.
Ok, I set it to nullable and it keeps overwriting the database as a null value. I guess its impossible to do this since technically null is a valid value for the column and if I pass an object to the function, the empty values must contain something or be null.
So I would have to explicitly state to take the database value for that column
Thanks

Resources