EDIT: I think I need some sort of view model, but I'm unsure how to handle this relationship.
I'm trying to understand MVC 4 and EF Code First and I'm trying to map many to many relationships.
I have two classes;
public class Asset
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public virtual ICollection<Category> Categories { get; set; }
}
public class Category
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public string Description { get; set; }
public virtual ICollection<Asset> Assets { get; set; }
}
So I'm trying to allow each Asset to have multiple Categories and each Category may have multiple Assets.
On my create method I have;
public ActionResult Create()
{
var model = new Asset();
model.Categories = _db.Categories.ToList();
return View(model);
}
In my view, the only way I can show these categories is to say; (Note the capital M in Model. I can't use the lower case model as used elsewhere in the view)
#model MyProject.Models.Asset
#using (Html.BeginForm("Create", "Assets", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
#foreach (var item in Model.Categories)
{
<p>#item.CategoryName</p>
}
</div>
<div class="form-group">
#Html.LabelFor(model => model.Title, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Title, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Title, "", new { #class = "text-danger" })
</div>
</div>
}
When the initial create is called, I can see my asset and it has categories. On the return create method however, its null. I can't work out why. I understand I'm not doing anything to edit these categories in the View, I can't get that far. What I don't understand though is why my model leaves with categories, but comes back with none.
My create return (here my assets categories is null)
// POST: Assets/Create
[HttpPost]
public ActionResult Create(Asset model)
{
if (!ModelState.IsValid)
{
//error, return to view.
return View();
}
try
{
//do stuff
}
catch
{
return View();
}
}
Ultimately when creating an Asset, I want to be able to list all the categories and allow some selection as to which categories this new asset will belong. If someone could help me work that out, you're my hero. But if I could just understand why what's coming back isn't what I sent out, that would be a start.
In my view, the only way I can show these categories is to say; (Note the capital M in Model. I can't use the lower case model as used elsewhere in the view)
I've always hated that Microsoft uses the model => model.* convention through its generated views and tutorials and articles online; it only leads to confusion. In your view Model is an actual object instance, namely an instance of what you defined as the "model" for the view. The lowercase model you see used in things like Html.EditorFor is actually a parameter to a lambda expression. It can be called anything. For example, Html.EditorFor(x => x.Foo) and even Html.EditorFor(supercalifragilisticexpialidocious => supercalifragilisticexpialidocious.Foo) would work just as well. Although the value that gets passed into this parameter is usually the Model object instance, Model and model are totally different concepts.
When the initial create is called, I can see my asset and it has categories. On the return create method however, its null. I can't work out why. I understand I'm not doing anything to edit these categories in the View, I can't get that far. What I don't understand though is why my model leaves with categories, but comes back with none.
That is why. You're not doing anything to edit these categories in the view. There's no fields for them to be posted along with the form data, and as a result, the class instantiated by the modelbinder in your action does not contain any data for categories. This is key. The class instance that goes into the view is not the same class instance that comes back after something like a post. Each is a unique thing. The post action has no knowledge of anything that came before it; it simply has whatever data was posted. Assuming the action takes a parameter of a particular class, the modelbinder will attempt to new up an instance of that class and bind the posted data to appropriate properties on that class. It doesn't care what was sent to the view originally; it doesn't even care what class it's working with.
Ultimately when creating an Asset, I want to be able to list all the categories and allow some selection as to which categories this new asset will belong. If someone could help me work that out, you're my hero. But if I could just understand why what's coming back isn't what I sent out, that would be a start.
This is the fun part. First, you absolutely must use a view model for this. In case you're not familiar with view models, they're simply classes that are used as a model for a view, hence the name. What you're passing around here, Asset, is technically an "entity", which is a class that is used for data transfer, usually to/from a database. While an entity could be used as a model for a view, as you've done here, it's not really suited for that.
There's a clear conflict of interest, as the needs of a class representing some table schema in a database are vastly different from the needs of a class representing data for a UI layer. That's where view models come in. In the most traditional sense, a view model simply represents the data that will need to be displayed and/or edited in one or more views. It may have many properties in common with a particular entity or it may only have a subset of those properties or even completely different properties. It is the job of your application to "map" from your entity to your view model and vice-versa, so that the logic for saving an entity to a persistence store can be completely abstracted from the logic for how the user interacts with that data.
The reason a view model is so important for your purposes here is that form elements in HTML have certain limitations. They can only work with data that can be represented as a string: things like ints, bools, actual strings, etc. They are particularly unsuited for working with complex objects, like your Category class. In other words, it would be perfectly achievable to post back a list of integer ids, representing Categorys, but it is entirely implausible to post back complete Category instances that have been chosen by a user.
Since your entity expects a list of categories and your view will only feasibly be capable of posting a list of ints, there's a fundamental disconnect. Using a view model provides a way to bridge the gap. Plus, it allows you to have other properties, like a list of category choices to populate your select list with, that would be totally inappropriate to put on your entity class.
For your scenario, you'd need a view model like:
public class AssetViewModel
{
// any other asset properties you need to edit
public List<int> SelectedCategoryIds { get; set; }
public IEnumerable<SelectListItem> CategoryChoices { get; set; }
}
This then allows you to create a multiselect list in your view using:
#Html.ListBoxFor(m => m.SelectedCategoryIds, Model.CategoryChoices)
Now, to populate your view model with data from your entity. In a create view, the entity doesn't exist yet, so you don't need to do any mapping. The only thing you need to do is populate your CategoryChoices property so the select list in the view has some data. However, based on the above discussion about data needing to be posted back or else it will be null, since the actual contents of the select list will never be posted, you'll need to populate this in each of your create and edit actions, both for GET and POST. As a result, it's best to factor this logic out into a private method on your controller that each action can call:
private void PopulateCategoryChoices(AssetViewModel model)
{
model.CategoryChoices = db.Categories.Select(m => new SelectListItem
{
Value = m.Id,
Text = m.Name
};
}
Then, in your create GET action, you'll just new up your view model and populate your category choices:
public ActionResult Create()
{
var model = new AssetViewModel();
PopulateCategoryChoices(model);
return View(model);
}
In the post version, you'll now need to map the posted data onto your Asset entity:
[HttpPost]
public ActionResult Create(AssetViewModel model)
{
if (ModelState.IsValid)
{
var asset = new Asset
{
Title = model.Title,
Description = model.Description,
// etc.
Categories = db.Categories.Where(m => model.SelectedCategoryIds.Contains(m.Id))
}
db.Assets.Add(asset);
db.SaveChanges();
return RedirectToAction("Index");
}
PopulateCategoryChoices(model);
return View(model);
}
The edit GET action is similar to the create version, only this time, you have an existing entity that will need to be mapped onto an instance of your view model:
var asset = db.Assets.Find(id);
if (asset == null)
{
return new HttpNotFoundResult();
}
var model = new AssetViewModel
{
Title = asset.Title,
Description = asset.Description,
// etc.
SelectedCategoryIds = asset.Categories.Select(m => m.Id).ToList()
};
Likewise, the edit POST action is similar to the create version, but you're going to map from your view model on to an existing asset instead of creating a new asset. Additionally, because you have a many to many relationship, you have to take extra care when saving the categories.
// map data
asset.Title = model.Title;
asset.Description = model.Description;
//etc.
// You might be tempted to do the following:
// asset.Categories = db.Categories.Where(m => model.SelectedCategoryIds.Contains(m.Id));
// Instead you must first, remove any categories that the user deselected:
asset.Categories.Where(m => !model.SelectedCategoryIds.Contains(m.Id))
.ToList().ForEach(m => asset.Categories.Remove(m));
// Then you need to add any newly selected categories
var existingCategories = asset.Categories.Select(m => m.Id).ToList();
db.Categories.Where(m => model.SelectedCategoryIds.Except(existingCategories).Contains(m.Id))
.ToList().ForEach(m => asset.Categories.Add(m));
The extra footwork here is necessary to prevent saving the same relationship twice, resulting in an integrity error. By default Entity Framework creates a join table for many to many relationships that consists of a composite primary key composed of the foreign keys to each side of the relationship.
The reason why your categories is null is because you are not binding it on the POST. They are not in fields during the POST.
Try this and see if they are filled out:
#for (int i = 0; i < Model.Categories; i++)
{
#Html.TextBoxFor(model => model.Categories[i].CategoryId)
#Html.TextBoxFor(model => model.Categories[i].CategoryName)
}
1.
return View();
you are not passing back the model in your Create Method that is why you don't see the Model is NULL.
// POST: Assets/Create
[HttpPost]
public ActionResult Create(Asset model)
{
if (!ModelState.IsValid)
{
//error, return to view.
return View(model);
// If you don't pass back the model to you view you will see model is NULL
}
try
{
//do stuff
}
catch
{
return View(model);
}
}
Cateogries Will always be null in your case, as you can't post back a List like you are doing in your case.
Try Displaying them in a loop, Then the MVC model Binder will be able to bind your list to Model:
#for (int i = 0; i < Model.Categories; i++)
{
#Html.HiddenFor(model => model.Categories[i].CategoryId)
}
If you want to save SelectedCategories you will have to use MultiSelect
Related
My target is, to modify a model in more than one view.
Since sometimes my models have many properties I want to modify them in more than one view. Something like:
first page edits 2 properties, second page edits 3 other properties,...
the model looks like this:
public class LoadViewModel
{
public int CurrentPage { get; set; } = -1;
public PageViewModel PageViewModel { get; set; }
}
public class PageViewModel
{
public string Param1 { get; set; }
public string Param2 { get; set; }
public int Param3 { get; set; }
}
my view on the Index-page looks like this:
#model LoadViewModel
#using(Ajax.BeginForm("Load", "Home", new AjaxOptions {UpdateTargetId = "page"}, new {lvm = Model}))
{
<div id="page"></div>
<input type="submit"/>
}
and this is my action:
public ActionResult Load(LoadViewModel lvm = null)
{
if (lvm == null) lvm = new LoadViewModel();
lvm.CurrentPage += 1;
TempData["CurrentPage"] = TempData["CurrentPage"] == null ? 0 : (int)TempData["CurrentPage"] + 1;
if (!partialViewDict.ContainsKey((int) TempData["CurrentPage"]))
TempData["CurrentPage"] = 0;
return PartialView(partialViewDict[(int)TempData["CurrentPage"]], lvm);
}
the pages are just partials that are mapped:
private Dictionary<int, string> partialViewDict = new Dictionary<int, string>
{
{0, "Pages/_Page1"},
{1, "Pages/_Page2"},
{2, "Pages/_Page3"},
};
and designed like this:
#using WebApplication1.Controllers
#model LoadViewModel
#{
TempData["CurrentPage"] = 0;
}
#Html.DisplayNameFor(m => m.PageViewModel.Param1)
#Html.EditorFor(m => m.PageViewModel.Param1)
this is working. When switching to Page2 the model is correctly set, but when hitting the submit the value of Param1 (that I set in Page1) is resetted to null and only the values I set in the current partial are correct.
This is Page2:
#using WebApplication1.Controllers
#model LoadViewModel
#{
TempData["CurrentPage"] = 1;
}
#Html.DisplayNameFor(m => m.PageViewModel.Param2)
#Html.EditorFor(m => m.PageViewModel.Param2)
When I add a #Html.HiddenFor(m => m.PageViewModel.Param1) into the partial, the value is still set. But I don't want the values to be resetted. I don't want to add an #Html.HiddenFor for all properties a set in a previous view. How can I prevent that the values are resetted when hitting submit without adding #Html.HiddenFor for all not listed attributes? Or is there any other possibility to catch my target?
There's two pieces to this. First, the post itself, and getting that to validate. For that, each step should have its own view model, containing only the properties it's supposed to modify. This allows you to add all the validation you need without causing other steps to fail. In the end, you'll combine the data from all of these into your entity class or whatever.
Which brings us to the second piece. You need some way of persisting the data from each step. The only data that will exist after a POST is the data that was posted and anything in the session (which includes TempData). You could always create a bunch of hidden fields to store the data from the previous steps, but that can get a little arduous. Most likely, you'll just want to use the session.
TempData is basically a specialized instance of Session, so which you use doesn't really matter. With TempData, you'll need to remember call TempData.Keep() for each of the keys you've set for each step or you'll lose the previous steps on the next request. Session will keep them around for the life of the session, but you should remember to remove the keys at the end with Session.Remove().
Do you use #using (Html.BeginForm()) in your .cshtml?
Unfortunately this is MVC. MVC is stateless, which means if you don't render it then you loose it :(
If you use model binding and scaffolding, then you can save some time and work but at the end it will be the same solution.
The background for my C# knowledge is 0. I am trying to learn it as I go. I just am not sure how to use the right words to search. So I am crying for help !
I have a small ASP.Net Web application that uses MVC framework. I have a Database which hold three tables Company, Territory, the third is a relationship table TerritoryCompany. So the basic set up is one Company can have branches in several Territory, and one Territory can have several Company. The relationship is Many-Many.
What I have is a CS Code that will allow you to create a company, nothing fancy, just
public void Save(CompanyModel company)
{
using (var db = new SampleDbContext())
{
Company entity;
if (company.CompanyId > 0)
{
entity = db.Companies.First(x => x.Id == company.CompanyId);
}
else
{
entity = new Company();
db.Companies.Add(entity);
}
entity.Name = company.CompanyName;
entity.PhoneNo = company.PhoneNo;
//What should I do?
db.SaveChanges();
}
}
Now as you see, I am able to add the Company Name and Phone Number. Good. This is the code I use in the Webpage,
#model PEF.SampleTesting.Domain.CompanyModel
#{
ViewBag.Title = "Add";
}
#using (Html.BeginForm("Save", "Companies"))
{
#Html.EditorForModel()
<label>Enter the list of service area</label><br />
<input id="ServiceArea" class="form-control" name="testBox" value="eg. BS1, BA5" /><br/>
<button type="Submit" class="btn btn-primary">Save</button>
}
Here is the CompaniesController
[HttpPost]
public ActionResult Save(CompanyModel model)
{
if (!ModelState.IsValid) return View((model.CompanyId == 0)?"Add":"Edit", model);
_companyService.Save(model);
return RedirectToAction("Index");
}
What I would like to do is, before doing the save changes db.SaveChanges(); when the company is created, I would like to
Add these entries for the Territory - if the territory does not exist in the Territory table
or
Create an entry in the relationship table for that CompanyID and the corresponding TerritoryID) for that particular Company.
I created a TextBox that will get a comma separated entry of territories. Use this TextBox value in a For and create as many entities to the table Territory (using for loop and split function maybe).
My Questions;
How would I pass the form value (TextBox) back to the code?
How can I use the For Loop to add this 'n' number of entries to the TerritoryCompany table?
Any helps or steps would be greatly appreciated.
Typically instead of passing your data entities to your view you would create a viewmodel, that will provide you with more flexibility...
Something like this class "AddCompanyViewModel", it has a property for your Company and also a property for your comma separated string of territories...
You will now pass this viewmodel too and from your controller instead of the entity type... this is a common scenario as your database structure will rarely perfectly match your domain layer (business layer)... view models essentially model your view.
public class AddCompanyViewModel
{
public CompanyModel Company { get; set; }
public string Territories { get; set; }
}
[HttpPost]
public ActionResult Save(AddCompanyViewModel model)
{
if (!ModelState.IsValid)
return View((model.Company.CompanyId == 0)?"Add":"Edit", model);
_companyService.Save(model.Company);
// Do something with territories...
var territories = model.Territories.Split(',');
return RedirectToAction("Index");
}
You can use the FormCollection parameter for the action.
public ActionResult Save(CompanyModel model, FormCollection formCol)
Reference the textbox via the name property.
Not quite sure about what you're asking for. You can use the Foreach loop to loop through each territory after you've split the textbox value. Then you create your TerritoryCompany model and save accordingly.
Could you explain the interaction Models and ViewModels in the ASP.NET MVC?
If I need to display data on the page, but not edit, whether to create a ViewModel to display or use the Model?
I have two methods in the repository. One returns the Model and the other Model gets.In View I need to send the model. Should I convert the resulting Model to a ViewModel that would pass it to the View, and upon receipt of the submission to convert it back into the model to keep it?
For example I have a class model and class ViewModel.
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public int Price { get; set; }
}
public class EditItemItemViewModel
{
public string Name { get; set; }
public int Price { get; set; }
}
On the edit page, I clicked the edit item, and must get to the controller:
[HttpGet]
public ActionResult EditItem(int id)
{
//some code
return View();
}
Where can I get the ID if I passed in the view ViewModel in which there was no ID?
If I somehow got the ID, I need to do the following, which would save the model?
[HttpPost]
public ActionResult EditItem(EditItemItemViewModel ViewModel)
{
var Item = _dataManager.Items.GetItemById("1");
Item.Name = ViewModel.Name;
Item.Price = ViewModel.Price;
_dataManager.Items.AddItem(Item);
return View("Sucsess");
}
Could you tell me how to work with Models and ViewModels?
You can get the id a few different ways:
#Html.HiddenFor(m => m.Id)
This will include the property in the actual HTTP request.
Another option is to simply include the id as part of your route (this is what I usually do):
#Html.BeginForm("EditItem", "SomeController", new { Id = Model.Id }, FormMethod.Post) {
...
}
In both instances, make sure to validate that the user should be able to update the record that corresponds to that id! There's nothing stopping a user from tampering with the id and sending you a different value.
As for whether or not to display the database model or the view model, that's really up to you. I would always advocate building a view model and keep your database models out of the picture except for in your controller. The convention I use at work is for every database object that I need to send to users I will create a corresponding view model. So if I have a database object called Product I will build another class for the view called ProductModel.
An advantage of following that pattern is something I actually explained to another user earlier in regards to model binding.
If I need to display data on the page, but not edit, whether to create a ViewModel to display or use the Model?
If it's very simple (like your example) and the properties map 1-1 like they do now. I would just use the Model as a view model, it's easier. Though if you want you could create a view model with the exact same properties and populate that and display it..it's a bit more work, but makes it so your domain models aren't necessarily tied to your views.
If you do that you may want to look into something like AutoMapper which would allow you to do something like
//simply copies the properties from one type to another
var viewModel = Mapper.Map<Item, EditItemItemViewModel>();
I have two methods in the repository. One returns the Model and the other Model gets.In View I need to send the model. Should I convert the resulting Model to a ViewModel that would pass it to the View, and upon receipt of the submission to convert it back into the model to keep it?
If you go the view model route then yes, you will end up doing a lot of converting between model and viewmodel, that's where something like AutoMapper can help out, or you can just create a couple extension methods that convert between the two types.
It looks like Justin Helgerson's answer explaining a way to handle models/viewmodels is pretty good.
Your posting your viewmodel, so i'm going to assume that you've referenced your model within the page
#model MyNameSpace.EditItemItemViewModel
Is there a reason the id is not included in your view model? The easiest method would be to include that in the model and pass the instantiated model when creating the view.
[HttpGet]
public ActionResult EditItem(int id)
{
var myViewModel = new EditItemItemViewModel() { Id = id };
return View(myViewModel);
}
Like Justin said, it is easier to put it in a hidden field somewhere inside the #Html.BeginForm as the id should just be for reference.
[HttpPost]
public ActionResult EditItem(EditItemItemViewModel viewModel)
{
var Item = _dataManager.Items.GetItemById(viewModel.Id);
Item.Name = viewModel.Name;
Item.Price = viewModel.Price;
// Should this be an Add?
_dataManager.Items.AddItem(Item);
return View("Success");
}
Hi I have simple model which looks like this:
public class HomeModel
{
public HomeModel()
{
Buildings = new List<Building>();
}
public List<Building> Buildings { get; set; }
public int SelectedBuildingId { get; set; }
}
and on view i display combo like this:
#Html.DropDownListFor(model => model.SelectedBuildingId, new SelectList(Model.Buildings, "Id", "Name"), "Choose Building... ")
and now when I click submit button, then the buildings list dissapears
so I tryid to keep it with hidden field
#Html.HiddenFor(model => model.Buildings)
but it doesn't work, any help ?
#Html.HiddenFor(model => model.Buildings) -> this is working just for primitive types like int string and so on.
I will not recommend you to serialize a list into the view but if this is necessary for you,you can do it like this:
#for (int i = 0; i < Model.Buildings.Count; i++)
{
#Html.HiddenFor(c => c.Buildings[i])
}
And now after post you will have full list in your view.
If your view is strongly typed to your HomeModel, then you can return your model in your postback event and return the model again to your view:
[HttpPost]
public ActionResult GetHomePostResult(HomeModel model)
{
//do whatever with your model data
return View("YourHomeGetView", model);
}
You don't need the list again... just load it again in the Post action.
EDIT:
If you insist in having it posted along with the important data. You should serialize that list to a string, and then rebuild the list in the server after the post.
Remember you are in MVC not plain ASP.NET... so each action is somehow atomic. For the case of dropdownlists, this is the normal behavior: reload the list in the server (independently from where you load it).
1)
and now when I click submit button, then the buildings list dissapears so I tryid to keep it with hidden field
#Html.HiddenFor(model => model.Buildings)
but it doesn't work, any help ?
Just Inspect element and see what is the name rendered for this hidden field, Make sure you have the same name as in your Model (only then the values get binded). If you see a different name in element, change the syntax to
#Html.HiddenFor(model => model.Buildings, name {Name = Buildings })
and on post back the values will be binded in the model
**OR**
2) If you are retrieving the values from DB using some Id or something. Pass this Id to the view. And keep this in hidden field. On post back catch this value in controller with proper parameter name (Name must be same as the hidden field element in view). Use this Id to retrieve the DropDown again and continue...
I'm new to MVC and am attempting to adhere to best practices.
I'm creating an edit/save form for contacts using an existing data project with several classes I need to load and save together on one form.
For the contact, I need to load a Person's name, company details, phone #s, address fields, etc.. Each of these is a separate class in the data project, but I want to edit and save within one view/model. The issue is that I seem to have to put all the necessary PK and FK IDs on my view as Hidden fields, and it feels like there should be a better way to do it...
For my model, I use existing data class objects as the fields:
public class ContactEditModel
{
public Person PersonObjectName { get; set; }
public Company CompanyObjectName { get; set; }
public Address AddressObjectName { get; set; }
....
}
I instantiate an object for each of these and load them within my model, and I want to save any changes on submission of the Edit view.
Since I already have load and save methods for these classes (as well as stored procedures to do the work) in the existing data project, it seemed to make sense to re-use the code rather than specifying all the fields on the model and re-writing code.
However, without declaring all the hidden fields on the view, the IDs (person, company, address, etc.) aren't preserved in the model when saving, thus I have to specify each field I want preserved in a Hidden item.
The hidden fields code example is below:
#Html.HiddenFor(model => model.PersonObjectName.ID)
#Html.HiddenFor(model => model.PersonObjectName.Version)
#Html.HiddenFor(model => model.PersonObjectName.CompanyID)
#Html.HiddenFor(model => model.AddressObjectName.ID)
#Html.HiddenFor(model => model.AddressObjectName.AddressTypeID)
#Html.HiddenFor(model => model.AddressObjectName.Version)
.....
Any ideas on a better way to do this would be greatly appreciated.
Thanks.
The answer to this kind of question is always "it depends" and much of it is based on personal preference, or how you are doing things.
For instance, I prefer not to include all those ID's, but rather have a single parent id which I can then use to lookup the other ID's on POST. This means you only need to save one hidden field (or even just have it be part of the url, so no hidden necessary). In your case, probably the PersonObjectName.ID.
If you'd rather not do another lookup, then you can include those ID's, however you need to consider whether or not this is sensitive information. For instance, what happens if someone uses Fiddler to change the Address id to something else? You now have to add logic to ensure that the user isn't allowed to update addresses that are not linked to his id.
For things like this I normally use TempData.
TempData is basically session, but its only available for one request.
So on the Edit get method I will put whatever IDs I need to store into TempData and then read them out when the form is posted.
You can follows the steps as follows:
Designing the model :
public class ContactEditModel
{
public string PersonObjectName { get; set; }
public string CompanyObjectName { get; set; }
public string AddressObjectName { get; set; }
....
}
Create strongly type views :
#model MyModels.ContactEditModel //Model Namespace
#using (Html.BeginForm())
{
#Html.TextBoxFor(m => m.PersonObjectName )
#Html.TextBoxFor(m => m.CompanyObjectName )
#Html.TextBoxFor(m => m.AddressObjectName )
#Html.ValidationMessageFor(m => m.Password)
<input type="submit" value="Log In" />
}
Working with Action
public ActionResult Edit(ContactEditModel model)
{
return View(model);
}
[HttpPost]
public ActionResult Edit(ContactEditModel model)
{
// Implementation
// model will have all updated values from UI
return View(user);
}