In a previous post (ASP.NET MVC 5 Model-Binding Edit View), the answer suggested this Controller code to process an edit-view postback:
public ActionResult Edit(WarrantyModelEditViewModel vm)
{
if (ModelState.IsValid)
{
var warranty = db.Warranties.Find(vm.Id);
.
.
.
}
Question:
Is re-querying the database for the warranty in question really the only way to do this in MVC and is it considered a best-practice approach? (I saw this post, How to re-use model data on post back with MVC, but it was a bit dated so I want to be sure my information is current as of MVC 5 and EF 6.)
In addition, I imagine there are various database concurrency issues, such as if the record was modified or deleted by another user after the view is rendered but before postback. Are there any good resources that discuss ways of handling the various scenarios?
You can also do an attach the entity which requires only one call to database. Check this solved thread.
In short something like this -
db.Users.Attach(updatedUser);
var entry = db.Entry(updatedUser);
entry.Property(e => e.Email).IsModified = true;
// other changed properties
db.SaveChanges();
For your second question to get optimistic concurrency, you can have a column called timestamp and can check for it during updates. Check this tutorial - Handling Concurrency with the Entity Framework in an ASP.NET MVC Application
Related
I am relatively new to MVC. I am trying to just display the contents of a remote SQL Server table on a page. It is READ ONLY, and nearly everything I find online is utilizing the Entity Framework or something similar which is overkill for what I am after. I just need to print all the rows from a table out to a view.
So my questions are:
should I just hack the sqlconn and everything into the view that I want the data printing out to?
Or should I add the sql in that view's controller?
Create a model and somehow get that data back into the view?
I know step #3 is the 'correct' way to do it, however I am looking for something simple and quick. :)
Thanks everyone!
You say EF is overkill, but that's the easiest way to do this. Maybe use Linq to SQL, since that's more lightweight. This is all there is to it:
Generate the EF / L2S entity classes
Instantiate the database context in the controller, and get all records
Return the IEnumerable records to the view
In the view, use #Html.DisplayForModel()
Here's a simple example. Note that returning the database entity classes is considered bad practice, you should map / automap them to a View Model type class first.
Home Controller
public ActionResult Index()
{
MyEntityModel[] items = MyDatabaseContext.GetAllRows();
return View(items);
}
Home/Index View
#model IEnumerable<MyEntityModel>
#foreach (MyEntityModel item in Model)
{
#Html.DisplayFor(m => item)
}
Without EF / L2S it's almost as easy, but you'd have to create your own entity / wrapper class for the database records and populate them manually.
There are also scaffolding projects for MVC that will generate repository and controller classes, as well as Razor views. See for example MVC Scaffolding on NuGet.
Once you get used to forcing yourself to use Entity Framework for even your "small" applications then and only then will you truly understand that is it the simplest way.
Sure, if you come from a background of memorized ADO.NET dataset/datatable/datareaders etc.. then sure you have projects with "canned" operations that you port over and modify but it is truly just old and cost you more time in the long run.
Use EF
Use multiple projects in a solution
Use a repository pattern if you can, it pays off in dividends for reasons you will discover
Keep your controllers "skinny"
Dont' use a "ViewModel" just to use / do it.
The SOC of having View and Controller are critical, but the Models folders does not need to be used, you can wire things up without it if you want, just pay attention to where your "model" is and abiding by SOLID principle etc..
I have an [HttpPost] action method signature like this:
[HttpPost]
public ActionResult Edit(ExistingPostViewModel model)
{
// Save the edited Post.
}
Now, in the past (when i didn't use ViewModels, e.g R&D), i had an implementation of an Edit method like this:
[HttpPost]
public ActionResult Edit(Post model)
{
var existingPost = repo.Find(model.Id);
TryUpdateModel(existingPost);
repo.Save(existingPost);
return RedirectToAction("Success", existingPost.Id);
}
Which worked great.
But i'm confused how to adapt the above to the ViewModel approach.
If i do this:
TryUpdateModel(existingPost)
With my ViewModel approach, not much happens. No errors, but nothing is being updated because MVC won't know how to update a Post from a ExistingPostViewModel (before it was Post -> Post).
Now, i'm using AutoMapper. So i thought i could map from the ViewModel to the Post, then save the post.
But then im basically overriding everything. Which i don't want to do and defeats the point of the cut down ViewModel.
Can anyone un-confuse me?
This seems like a really common scenario, and i am totally stumped as to how people solve this. I can only see 3 possible solutions:
Don't use a ViewModel in the HTTP POST. As i said i did this in the past for R&D and it works, but now i see how my View's have evolved (validation, simplicity), and i can't compromise that just for the sake of this problem.
Don't use TryUpdateModel. Possibly, but then how would i merge in the changes?
Use left-to-right. Ugh. But at the moment this seems to be the way im leaning.
Someone please give me solution #4! :)
BTW, i'm using ASP.NET MVC 3, Razor and Entity Framework.
I actually ran into this exact same issue in a project I'm currently working on. As much as I wasn't a fan of it, I ended up doing the left to right approach and manually mapping my viewmodel data back to my entity.
The only nice thing about this approach is it does give you more control. Since I started using more compound viewmodels, where you actually have fields from more than one entity in your viewmodel, it started making more sense to do things this way.
I'm also using AutoMapper, and you're absolutely right, it does get awkward when you're trying to do a simple update operation. Wish I had some super clever workaround for you, but the "old fashioned way" seems to get the job done best for the work I've been doing.
Not sure if this will help, but it is working for me. I have my underlying domain table as a Visitor Object. My viewmodel contains the Visitor Object plus a couple of IEnumerables for dropdowns.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id)
{
Visitor Visitor = new Visitor();
Visitor = db.Visitors.FirstOrDefault(v => v.VisitorID == id);
UpdateModel(Visitor, "Visitor");
db.SaveChanges();
return RedirectToAction("Index");
}
The UpdateModel works off my viewmodel because of the "Visitor" string telling it what values to compare.
For simple things where you don't have to run any controls prior to implementing the update what you are doing is okay (db.get(), and then update).
When things get complicated, you have to load the entity, and then select and apply user's changes from the view model, property by property. In those cases, you end up writing Update methods, which gets the new data as input, and then you load the existing entity, then compare states, and take the required actions based on the view model data. Actually in this case, probably you wont have an Update method but will have behaviors, like CancelPost, AddComment, EditPost (which also logs the edit reason), AddTagsToPost etc.
As I review more code and blog posts from lots of MVC sources, I still haven't wrapped my mind around what is "posted" when a request is made. I realize MVC doesn't support post, but I'm having trouble finding resources that can explain it well enough to understand.
Inside the controller's public ActionResult nameOfAction(what the heck goes here?) { ... } what are my parameters?
Sometimes it looks like Visual Studio scaffolds (int id, MyObject myobject) for an Edit-style action--it includes something from my model, but not always.
Sometimes, it's (int id, FormCollection collection) for a delete-style action. Why not use the modeled object here? Is a FormCollection object always "posted"?
Sometimes, I see (RouteInfo routeInfo) which isn't recognized in my MVC2 Intellisense (is this MVC1 only or something?)
How can/do/should I establish these parameters? I think this will help me a lot at design time.
What gets post back from a form in MVC is the form data which includes each form element in a keyvalue pair.
If you only need this information then you would use:
public ActionResult nameOfAction(string name, string lastName, string etc)
MVC has some smart data model binding which takes the form data and automatically creates an object which is part of you domain model. For instance it could automatically create a Person object with the provided form data.
I believe there is a security concern with this as a user of your site may post data which is not part of your form and guess what your models are to inject their own data.
I dont think this is a massive issue though and this is the way I would go.
I think you can use the anti-forgery helper to prevent users from posting back data which is not allowed in a form. anti-forgery
Use strongly typed views with a view-model and the strongly typed helpers. Then when you POST, you should get an instance of that view-model out.
I am using ASP.NET MVC2 with NHibernate, but am facing an issue. All calls to the database via NHibernate should be inside a transaction, however code inside the view kicks off database calls in some instances. Thus there is a need to be able to commit the transaction after the view has rendered.
For example displaying a list of users and their user roles you might show the user role using this code: <%: Model.UserRole.Name %>
This will cause a hit on the database as the UserRole is loaded using a NHibernate proxy.
You can fetch the UserRole eagerly which circumvents the issue in this case, but there are cases where it is much faster to use lazy loading.
Anyway, is there a way to run code after the view has rendered?
Have you tried to use session-per-request pattern? It's a very natural way of handling NHibernate sessions in web environment.
There are many information available when you do a Google search on "NHibernate session per request", like this blog post.
Also, take a look at great Bill McCafferty's article NHibernate Best Practices. Although it's written for NHibernate 1.2, it has a wealth of information. While there, his S#arp Architecture also looks very cool :)
How about an action filter?
public class CleanUpAttribute: ActionFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
//cleanup code here
}
}
Then you decorate your controllers with this attribute.
I'm wondering how you keep a constant value of the Model in an ASP.NET MVC framework. Like when adding something to the Model through the view. You go back to an action in the controller but where do you keep the Model? Is it a private in the controller? or is it passed back and forth from the view to the controller because if it gets big then you are passing alot of data back and forth to add/delete a single item from the Model.
Also any small examples to show this?
Thanks
What are you referring to? Are you meaning a database table loaded up into an object such as Ruby on Rails's ORM -- typically the 'Model' is a series of interfaces or domain objects that load data into objects from the database .. or more simply just the database period.
Please be more specific. There are many MVC frameworks and many different kinds of 'Models'
I think you should check out a ASP.NET MVC tuturial like NerdDinner (from "Professional ASP.NET MVC 1.0"). Scott Guthrie has posted a html version of the tutorial on his site. It's a fairly simple site that they build in the tutorial, and is a great intro to ASP.NET MVC (in my opinion).
There are also some good tutorials on the ASP.NET site.
Hope these help you with .NET MVC, it's a great framework to use!
You can pass the model to the page and you can then use UpdateModel(model name) within your controller.
Each member in the model must be a property with a getter and a setter.
On the page you can hold the data in say a hidden field if you need to maintain the value outside of state.
If you have problems using UpdateModel then you can use the following in your controller;
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult MyAction(int? id, FormCollection collection)
{
string commentText = collection["myFieldName"];
}
This will normally get your values from the model.
Hope this is what you were asking.
Think of the model as a data transfer object. In a list, display only or edit page, you pull it out of a data layer as a single object or a list of objects. The controller passes it along to the view and it gets displayed.
In the case of an insert, a new data transfer object is instantiated upon post back and is updated with the posted values. Then sent back to the the data layer for persistence.
In the case of an edit, it comes from the data layer on the HTTP GET request and is used to pre-populate the HTML form. Then on post back, the data transfer object gets updated with the posted values and sent back to the the data layer for persistence.
Definitely checkout NerdDinner or Stephen Walther's samples.