Best method to creating re-usable sections in asp.net-mvc
I have a开发者_C百科 form that I need in various parts of my website.
User's enter their address, and submit a form that saves the address. I want to wrap this up so I can re-use it since I need this exact same functionaility in a few places.
I am thinking to do this:
create a partial view with the form, but have the action location url passed in as a parameter.
create a seperate class/method that will handle the server side validation (UI has its own validation using jquery already)
saving/editing is already handled in the db layer.
Anyone have a better way to do this?
ASP.NET MVC uses convention over configuration so you can use this to submit your address form to different actions depending on where it was orginally requested from. So if you haven the actions:
public ActionResult Foo()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public void Foo(string address)
{
//code to update address
}
Your Foo.aspx view will contain your address partial view, and you're using the helper methods to create your form in your partial view:
<% using(Html.BeginForm()){ %>
.
.
.
<%}%>
Then when the form is posted, you can expect it to call your Foo action which accepts the HTTP Post.
Now, if create a new view called Bar.aspx which also contains your address partial view with two new actions to serve up your page and then accept the post data:
public ActionResult Bar()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public void Bar(string address)
{
//code to update address
}
You won't need to pass any data to your partial view to tell it where to post because the framework uses the naming conventions to work it out, ie when served up from /MyController/Foo, Html.BeginForm will render out /MyController/Foo as the action to post to. Same with /MyController/Bar
Hope thats sort of clear!
I'd often just create the form in those multiple places, use a separate ViewModel and wire that up to fire off the relevant command. But I'm not overly scared of duplication at that high a level in a project - and that's a personal preference thing.
I'd suggest in your case,using a partial view which assumes there is an object on your view model called Address, using a prefix in front of the names its binding to.
That object on your view model can be a shared object used on all the view models which require an address, let's say for convenience called "Address", of type "AddressViewModelComponent".
public class SomeViewModel
{
public string SomeFormValue
{
get;
set;
}
public string SomeOtherFormValue
{
get;
set;
}
public AddressViewModelComponent Address
{
get;
set;
}
}
public class AddressViewModelComponent
{
public string AddressLineOne
{
get;
set;
}
public string AddressLineTwo
{
get;
set;
}
// Etc
}
This way you can put an address on any view model that needs it, and your partial view could contain something like the following:
<li><%= Html.TextBox("Address.AddressLineOne") %></li>
<li><%= Html.TextBox("Address.AddressLineTwo") %></li>
Your actual view form would then look something like this:
<% using(Html.BeginForm()) %>
<ul>
<li><%= Html.TextBox("SomeFormValue") %></li>
<li><%= Html.TextBox("SomeOtherFormValue") %></li>
<% Html.RenderPartial("AddressForm"); %>
</ul>
<%} %>
The default model binder knows to look for an object called "Address" on the view model, and populate the property on that view model with the relevant property.
This might be overkill, and I've never found an instance where I've needed to "share" a form on my projects, but the above is probably where I'd start looking if I was to do it.
If the form is stand alone, you might consider making the form available in just a single controller. Add a hidden field to the form that holds a value for redirect. Once the data is posted and the controller updates the record in the database, it could read the value in the redirect field and then redirect to another controller.
Off the top of my head, something like this. It obviously needs to be fleshed out a bit:
AddressController:
public ActionResult Edit(int id)
{
return Edit(id, "Address", "Index"); // return to the Index page
}
public ActionResult Edit(int id, string controller, sting action)
{
Address address = MyDatabase.GetAddress(id);
ViewData["Action"] = action;
ViewData["Controller"] = controller;
return View(address);
}
public ActionResult Edit(Address address)
{
MyDatabase.Save(address);
// Read redirect from Form
string action = Request.Form["Action"];
string controller = Request.Form["Controller"];
return RedirectToAction(action, controller);
}
If you wanted to use the form from a different controller named Controller2, you would use something like this:
public ActionResult EditAddressHere(int AddressID)
{
return RedirectToAction("Edit", "Address", new { id = AddressID, controller = "Controller2", action = "Saved" } );
}
public ActionResult Saved()
{
return View();
}
I haven't included the view, but it should be simple enough to store the controller and action data in a hidden field of the form.
精彩评论