General .NET MVC2 questions
I am just getting into .NET MVC2 (.NET in general even) and I am having a hard time getting familiar with the "flow" of things. The MVC framework, I get.. for the most part. The part that I am getting tripped up on is applying standard programming practices to .NET MVC.
For example
public ActionResult Index()
{
var dataContext = new SiteContentDataContext();
var data = from c in dataContext.SiteContents where c.Slug == "home-page" select c;
// call/return getMainNav()
// call/return getSubNav()
return View(data);
}
public ActionResult SiteContent(string strSlug)
{
var dataContext开发者_运维知识库 = new SiteContentDataContext();
var data = from c in dataContext.SiteContents where c.Slug == strSlug select c;
// call/return getMainNav()
// call/return getSubNav()
return View(data);
}
private void getSubNav()
{
// get subnav records from db.
// return subnav records.
}
private void getMainNav()
{
// get main nav records from db.
// return main nav records.
}
The Index and SiteContent view are identical except for the fact that the Index view uses a different master page. Both views have a subnav and a main nav that will be dynamic content from a database.
The question, finally, is how would I go about populating the getSubNav and getMainNav functions and second, how would I return that data to the view properly?
Look into ViewModel objects, objects you create whose purpose in life is to carry data to and from your Views. The Models folder created for you by default in a new MVC project would hold exactly those classes.
You have options besides the ViewModel object methodology, but none are as clean. (The ViewData
dictionary is around to help but it's not intended to be the primary means of providing data to your views.) Here's an example of how to set the Model property of the ViewData object to an instantiated, populated viewmodel instance:
public ActionResult SiteContent(string strSlug) {
SiteContentVM model = new SiteContentVM();
SiteService siteService = new SiteService();
model.Slug = siteService.GetALittleSlimyCreature(strSlug);
model.List1 = siteService.GetList1();
model.List2 = siteService.GetList2();
ViewData.Model = model;
return View();
}
You can now create a strongly typed view (complete with intellisense) to reference any properties of your ViewModel object instance from within your view simply through the Model
property:
<% foreach (var item in Model.List1) { %>
<% Html.Encode(item.StringField) %> <!-- <= writing a property -->
<% Html.RenderPartial("PartialNameHere", item); %> <!-- <= the equivalent of a usercontrol -->
<% } %>
As you see above the process of getting data from the database does not change for MVC. You do it just as you would in a normal webforms project. (...usually this involves instantiating a business logic or service class of some sort rather than actually writing the code in the MVC project.)
Enjoy MVC!
You should look into DDD and TDD for ASP.NET MVC. For the looks of it you seem to be using Linq To Sql. I'm going to try to explain in a few words what I do to accomplish a good architecture.
Architecture
- DB Context
- Domain Model
- Repository Pattern
It's good practice not to tie your Database Context with your Controllers. What you want to do is have your Controllers call your Repository, which in turn will return your Model. Now here's the tricky part you must convert the DB Context Objects into your Model Objects.
Imagine you have an Products table which Linq To SQL will give you as the Products Class. That Products Class is part of the DB Context and what you want to do is alienate your context, in fact your Controllers won't even know it exists.
Why would I need a Model when I have Linq To SQL?
Well for starters LTS will regenerate all Objects everytime you change your Database meaning you wont have the ability to make change to the DB Context. And also you want to be able to use ASP.NET MVC 2 Annotations for validation and more.
Now create a Products Class for your Model
namespace MvcApplication.Models
{
public class Product
{
public int Id { get; set; }
[Required]
[StringLength(10)]
public string Name { get; set; }
[Required]
public string Description { get; set; }
[DisplayName("Price")]
[Required]
[RegularExpression(@"^\$?\d+(\.(\d{2}))?$")]
public decimal UnitPrice { get; set; }
}
}
Now you see this Class is part of the Model totally disconnected from the DB Context. Now what we do next is create our Repository Class.
namespace MvcApplication.Repository
{
public class AppRepository {
DbContext _context = new DbContext();
public IQueryable<Products> GetProducts()
{
return from p in _context.Products
select new Product {
Name = p.Name,
UnitPrice = p.UnitPrice
}
}
}
}
Now in your Controller you just call GetProducts();
public ActionResult SiteContent(string strSlug)
{
var repository = new AppRepository();
return View(repository.GetProducts());
}
Pretty isn't it.
You can use AutoMapper to map your DB Context objects to your Model objects. http://automapper.codeplex.com/
Well ,,, i think what you are looking for here is Partial Views.
You can embed the MainNav & SubNav Views into your SiteContent View.
here's how this goes.
create your MainNav & SubNav as partial views.
in your SiteContent view use the Html.RendarPartial Method to include the other two views.
<%= Html.RenderPartial("MainNav", Model); %>
<%= Html.RenderPartial("SubNav", Model); %>
Now to the remaining part about how to get the data to the MainNav & SubNav views. Now is a good time to get familiar with ViewModels. View models are nothing but classes with some properties that you want to give to a view to display.
In your case i would create 3 view models.
- SiteContentViewModel contains the content that will be displayed in your page.
- MainNavViewModel contains the data that will be displayed insdie the MainNav.
- SubNavVIewModel contains the data that will be displayed insdie the SubNav.
then i would include the MainNavViewModel & SubNavVIewModel inside the SiteContentViewModel.
(if you are sure that every SiteContent View will have a MainNav & a SubNav )
Now it's up to you to fill each view model with that data that you need.
here's how the code will look like.
public class SiteContentViewModel {
public MainNavViewModel MainNav { get; set;}
public SubNavVIewModel SubNav { get; set;}
// Any Other Data Needed In The SiteContent View (ex. PageTitle)
}
public class MainNavViewModel {
// Any Data Needed In The MainNav View
}
public class SubNavVIewModel {
// Any Data Needed In The SubNav View
}
Now back to the Partial Views ,,, using the View Models we created we can include the partials like this.
<%= Html.RenderPartial("MainNav", Model.MainNav); %>
<%= Html.RenderPartial("SubNav", Model.SubNav); %>
one important thing is to make our views strongly typed.
- SiteContent view of type SiteContentViewModel
- MainNav view of type MainNavViewModel
- SubNav vIew of type SubNavViewModel
and in your SiteContent action method you will do something like this
// Initialize the ViewModels.
SiteContentViewModel model = new SiteContentViewModel();
model.MainNav = new MainNavViewModel();
model.SubNav = new SubNavVIewModel();
// Get Data From DB and set the properties that you created in your view models.
// examples.
model.PageTitle = // some data from db.
model.MainNav.(Some Property) = // some data from db.
model.SubNav.(Some Property ) = // some data from db.
return View(model);
hope that helps ... for more information you can see this link
精彩评论