using System;MVC Storefront- Rob Conery reference tricky? - model-view-controller

I follow the StoreFront MVC Application video tuturial made by rob conery.
I noticed that the Commerce.MVC.Web reference both the Commerce.MVC.Data and Commerce.MVC.Services. This is because the Commerce.MVC.Web needs the Commerce.MVC.Data because of the entities defined with in it.
What is the better way to reference the Commerce.MVC.Services only. Do I need to put the Entities in the service?or any suggestions?
The bold text is came from Commerce.MVC.Data:
Commerce.MVC.Data
Commerce.MVC.Services- reference the Commerce.MVC.Data
Commerce.MVC.Web - reference both the Commerce.MVC.Data and Commerce.MVC.Services
Here the sample code from CatalogController:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Commerce.MVC.Data;
using Commerce.MVC.Services;
namespace Commerce.MVC.Web.Controllers {
public class CatalogController : Controller {
#region .ctor
ICatalogService _catalogService;
public CatalogController(ICatalogService catalogService) {
_catalogService = catalogService;
}
#endregion
#region ViewData
/// <summary>
/// Class used for transferring data to the View
/// </summary>
public class CatalogData {
public CatalogData() { }
public CatalogData(List<Category> categories, Category parent, Category child) {
this.Categories = categories;
this.Category = parent;
this.SubCategory = child;
}
public IList<Category> Categories;
//The below is came from Commerce.NVC.Data
public Product Product { get; set; }
public Category Category { get; set; }
public Category SubCategory { get; set; }
}
#endregion
}
}

Edited Response...
You can use the Service just fine, but the service returns something and that something is your Entities. In order for your Web app to use those Entities it needs to reference the class containing the Entities right?
Now you can get around this by returning Anonymous types, or maybe creating your own DTOs - but then you lose validations and everything the Entity has declared on it. In effect - you're duplicating your code.
Do you see this?

I don't think it matters massively (no pun intended) but we generally separate out the entities into a Model assembly which is shared across all layers.
So our structure is:
Company.Project.Model
Company.Project.Infrastructure
Company.Project.Web
Company.Project.Services
Company.Project.Data
The Model and Infrastructure (cross cutting concerns) are referenced across all layers with Web/Services/Data only able to talk to the layer immediately below.
Hope that makes sense.

I think the architecture in Rob's app is fine.
If you are worried that code from the website will call your data access code directly, rather than via the service, this is a legitimate concern.
However, if your website is setup with a dependency injection framework, you will not see data access classes being instantiated.
This should reduce the chances of someone new to your project instantiating data access classes directly, which obviously would be very bad...
This is why projects should always have code reviews. :)

I emailed this same question to Rob about a year ago and his response made me realise I was confusing the physical separation of code with the logical separation using namespaces.
If you still dont want to reference the entities from two different namespaces then you can use view models to dis-intermediate (and use a tool like automapper) however this is much more code.

Related

Web API is it necessary to have ViewModels layer classes?

When I use Web (MVC), I always to create a separate classes layer. These classes often the same as DTO classes, but with attributes like [Display(Name = "Street")] and validation. But for web api Display attributes are not necessary, validation can be used by FluentValidation. Should Api controller returns ViewModels classes or DTO classes will be fine too?
the answer, as always is .... it depends.
If your API is serving multiple clients , apps etc, then returning DTOs is a better options.
ViewModels are specific to the MVC client and should already be prepared for display, meaning the data should already be formatted in a specific way, some fields maybe combined, they should satisfy whatever requirements the display pages have. They are called ViewNodels for a reason. The point is that they are rarely exactly the same as the data the API returns, which should be a bit more generic and follow a certain pattern to make sense to its users.
If your ViewModels are exactly the same and you only have one client then it's up to you if you want to create a set of duplicated classed just to avoid having the attributes.
Mapping from DTO to ViewModel and viceversa is not exactly complicated, but the process does introduce one more complication, one more layer.
Don't forget one thing though. API DTOs are supposed to return the data they have on any entity regardless of the requirements of any UI. Requirements can change anyway, new fields added or discarded. You're more than likely to leave the API alone when that happens and simply change your ViewModels.
Your ViewModels are specific to a UI page and should contain only the data required by that page. This means that you can end up with multiple ViewModels for the same data, it's just that the display requirements are different for each.
My vote goes towards keeping the ViewModels and DTOs separate, even if, at this point in time they are exactly the same. Thins always change and this is one of those things you can actually be ready for.
Actually it depends on application's architecture how we want to return response. In this case yes we can return DTO classes but i think that would not be the good approach because we should create a separate Resource classes that will map with DTO and then return. Just see the below example:
public class CustomerDTO
{
public int ID { get; set; }
public string Name { get; set; }
public int DepartmentId { get; set; }
}
public class CustomerResource
{
[JsonObject]
public string Name { get; set; }
[JsonObject]
public string Department { get; set; }
}
Suppose we have CustomerDTO class and we want to return response in the following json format
{
"name":"Abc xyz",
"department":"Testing"
}
So in this case we should we have separate class that will return as a response to the end user as i created CustomerResource. In this scenario we will create a mapper that will map DTO with resource object.
And also with this implementation we can test resources independently

Model binding in controller when form is posted - why to use view model instead of class from domain model?

I'm still reasonably new to ASP.NET MVC 3. I have come across view models and their use for passing data from a controller to the view. In my recent question on model binding two experts suggested that I should use view models for model binding as well.
This is something I haven't come across before. But both guys have assured me that it is best practise. Could someone maybe shed some light on the reasons why view models are more suitable for model binding?
Here is an example situation: I have a simple class in my domain model.
public class TestParent
{
public int TestParentID { get; set; }
public string Name { get; set; }
public string Comment { get; set; }
}
And this is my controller:
public class TestController : Controller
{
private EFDbTestParentRepository testParentRepository = new EFDbTestParentRepository();
private EFDbTestChildRepository testChildRepository = new EFDbTestChildRepository();
public ActionResult ListParents()
{
return View(testParentRepository.TestParents);
}
public ViewResult EditParent(int testParentID)
{
return View(testParentRepository.TestParents.First(tp => tp.TestParentID == testParentID));
}
[HttpPost]
public ActionResult EditParent(TestParent testParent)
{
if (ModelState.IsValid)
{
testParentRepository.SaveTestParent(testParent);
TempData["message"] = string.Format("Changes to test parents have been saved: {0} (ID = {1})",
testParent.Name,
testParent.TestParentID);
return RedirectToAction("ListParents");
}
// something wrong with the data values
return View(testParent);
}
}
So in the third action method which gets invoked when an HTTP POST arrives I used TestParent for model binding. This felt quite convenient because the browser page that generates the HTTP POST request contains input fields for all properties of TestParent. And I actually thought that's the way the templates that Visual Studio provides for CRUD operations work as well.
However the recommendation that I got was that the signature of the third action method should read public ActionResult EditParent(TestParentViewModel viewModel).
It sounds appealing at first, but as your models and view actions get increasingly complex, you start to see the value of using ViewModels for (most) everything, especially input scenarios.
Case 1 - Most web frameworks are susceptible to over-posting. If you are binding straight to your domain model, it is very possible to over-post data and maliciously change something not belonging to the user. I find it cleaner to bind to an input view model than have long string lists of white lists or black lists, although there are some other interesting ways with binding to an interface.
Case 2 - As your input grows in complexity, you'll run into times when you need to submit and validate fields not directly in the domain model ('I Agree' checkboxes, etc)
Case 3 - More of a personal thing, but I find model binding to relational domain objects to be a giant pain at times. Easier to link them up in AutoMapper than deal with MVC's modelbinder for complicated object graphs. MVC's html helpers also work more smoothly against primitive types than deep relational models.
The negatives of using ViewModels is that it isn't very DRY.
So the moral of the story is, binding to domain models can be a viable solution for simple things, but as the complexity increases, it becomes easier to have a separate view model and then map between the two.

validation rules in mvc 3.0

I have one view model which is common for 3 to 4 views in this model I also define validation rules.Now problem is that in one of that view I want to overwrite that view model validation rules for two to three fields.so what I do? I don't want to make new view model for that view.
From an MVC architecture standpoint - this is exactly why you use view models.
You should create separate view models for each case. Use automapper (available for free on codeplex) to copy the values between your view model and your entity.
Don't even consider a different way, inheritance, etc - this is what ViewModels are for.
Three options I can think of:
Make a separate ViewModel using AutoMapper to handle some of the heavy lifting.
Make a subclass having different validation rules.
Make a custom ValidationAttribute which is context sensitive (Either by overriding the IsValid(Object, ValidationContext)method, or relying other context information from static methods/properties.
For instance, this Required validation attribute would be ignored if the request came from a certain URL:
public class CustomRequiredAttribute : RequiredAttribute
{
public override bool IsValid(object value)
{
if (HttpContext.Current.Request.Url != "urlwhennotrequired")
return base.IsValid(value);
return true;
}
}
If you do go ahead and use inheritance, then make sure that you inherit from abstract class. I think that as the system grows, you are likely to come across a scenario where your abstract class will have to be modified heavily,therefore If I were you, I'd create more view models, even if the code appears to be repetative. In the long term run you'll benefit because you'll be able to modify parts of your applications with as little side affects as possible.
My recommendation is basically what you don't want: create new model classes, but use inheritance to avoid repeating the properties you want. If you are adamantly opposed to creating separate models, you might look into implementing IValidatableObject and have it inspect other properties before validating the properties that you wish to vary.
EDIT:
I don't disagree with Tuliper's answer, but to flesh out my suggestions, consider a scenario in which you want to save a user's data. From one form, you are creating a user; from another, you are simply updating (this is a bit of a stretch but it's for purposes of illustration). The "create" form might require the name of a person referring the user, while the "update" form might not.
Using inheritance, you could do the following:
public class SaveUserModel
{
public int? UserId { get; set; }
...
}
public class CreateUserModel : SaveUserModel
{
[Required]
public string ReferredByName { get; set; }
}
Using IValidatableObject, you could do it this way:
public class SaveUserModel : IValidatableObject
{
public int? UserId { get; set; }
public string ReferredByName { get; set; }
...
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
// if UserId is null, we are creating a user vs. updating
if (UserId != null && string.IsNullOrWhiteSpace(ReferredBySiteUrl))
yield return new ValidationResult("Please specify the name of the person who referred you.", new[] { "ReferredByName" });
}
}
To reiterate, I am not trying to push my answer. I would be inclined to reuse models if they are exactly the same across different views, but generally there are enough differences to warrant simply creating separate models. In the end, any perceived technical debt alleviated by adhering to DRY in this situation would a bit of a wash; models tend to be easy to maintain.

localizing mvc 3.0 validation client messages

At first sorry for Microsoft MVC team because of no simple solution for localizing data annotation validation messages. It takes me a lot of time and finally no simple solution found!
I finally decided to inherit from RequiredAttribute to do localization. so I did this :
public class MyRequiredAttribute : System.ComponentModel.DataAnnotations.RequiredAttribute
{
public MyRequiredAttribute()
: base()
{
this.ErrorMessageResourceType = typeof(Resources.DataAnnotationDefaults);
this.ErrorMessageResourceName = "Required";
}
}
where I provided my localized messages in DataAnnotationDefaults.resx file.
So I can use this simply
[MyRequired]
public int UnitCode { get; set; }
But the problem is: it doesn't apply in client-side and just in server-side. why? what did I miss?
It is amazing that the following line is ok and works in client-side too!
[Required(ErrorMessageResourceName = "Required", ErrorMessageResourceType = typeof(DataAnnotationDefaults))]
public int UnitCode { get; set; }
I will be glad and appreciated if someone can help me on this.
You need to understand how validation works in MVC and .NET. DataAnnotation is a generic validation library which can be used in all kinds of applications and not just MVC.
Hence MVC contains different types of adapters for MVC which is used to add support for DataAnnotations. The client-side adapters are specifically made for the attributes defined in System.ComponentModel.DataAnnotations.
You therefore need to create your own adapters to get it working with your derived attributes. I've written a blog entry about it.
The easier approach is to use my localized metadata provider.

Beginner EF4 / CodeFirst / MVC3 help

Although I love what I'm learning, I'm finding it a struggle and need some help
I've been using these two tutorials which I think are awesome:
http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx
http://msdn.microsoft.com/en-us/data/gg685467
Currently my main problem/confusion is:
I have a CodeFirst table/entity I don't know how to correctly get data from other tables/entities to show in my views:
public class Car {
public int ID { get; set; }
public string Name { get; set; }
public int EngineID { get; set; }
public virtual Engine { get; set; }
}
public class Engine {
public int ID { get; set; }
public string Name { get; set; }
public string Manufacturer { get; set; }
// (plus a whole lot of other things)
}
Now when I create a View for Cars (using the List type/option) I get a nice autogenerated list
#foreach (var item in Model) {
<tr>
<td>#item.ID</td>
<td>#item.Name</td>
<td>#item.EngineID</td>
</tr>
Perfect... except EngineID is mostly worthless to the viewer, and I want to show Engine.Name instead
So I assumed I could use EF lazy loading:
<td>#item.Engine.Name</td>
Unfortunately when I tried that, it says my ObjectContext has been disposed so can't get any further data requiring a connection
Then I tried going to the controller and including the Engine.Name
var cars = (from c in db.Cars.Include("Engine.Name") select c;
Which tells me: Entities.Engine does not declare a navigation property with the name 'Name'
... ? Lies
Include("Engine") works fine, but all I want is the Name, and Include("Engine") is loading a large amount of things I don't want
Previously in a situation like this I have created a view in the DB for Car that includes EngineName as well. But with CodeFirst and my noobness I haven't found a way to do this
How should I be resolving this issue?
I thought perhaps I could create a Model pretty much identical to the Car entity, but add Engine.Name to it. This would be nice as I could then reuse it in multiple places, but I am at a loss on how to populate it etc
Wanting to learn TDD as well but the above is already frustrating me :p
Ps any other tutorial links or handy things to read will be greatly appreciated
It isn't lies as you are actually trying to include a property that's a 2nd level down withouth giving it a way to navigate. If you let EF generate your DB with this structure, it would likely have made a navigation table called something like Car_Engine and if you include the name without the object it HAS mapped, then it's not got a navigation property in your new object.
The simple way around this is to go:
(from c in db.Cars.Include("Engine") select new { c, EngineName = c.Engine.Name }
If you still get navigation property errors then you might need to make sure your are mapping to your schema correctly. This can be done with EntityTypeConfiguration classes using the fluent API - very powerful.
This of course won't help in strongly typing your car object to show in MVC.
If you'd like to get around this, your gut feeling is right. It's pretty common to use viewmodels that are read only (by design, not necessarily set to readonly) classes that provide simple views of your data.
Personally I keep my model quite clean and then have another project with viewmodels and a presentation project to populate. I'd avoid using overlapping entities in your core model as it might lead to unpredictable behaviour in the data context and at least a peristance nightmare when updating multiple entities (ie who's responsible for updating the engine name?).
Using you viewmodels, you can have a class called CarSummaryView or something with only the data you want on it. This also solves the issue of being vulnerable to overposting or underposting on your site. It can be populated by the above query quite easily.
PS There's a bunch of advantages to using viewmodels beyond just not loading full heirarchies. One of the biggest is the intrinsic benefit it gives you with avoiding over and underposting scenarios.
There's loads of ways to implement viewmodels, but as a simple CarView example:
public class CarView
{
public int ID { get; set; }
public string Name { get; set; }
public string EngineName { get; set; }
}
This should be clearly seperated from your entity model. In a big project, you'd have a single viewmodels project that the presenter can return, but in a smaller one you just need them in the same layer as the service code.
To populate it directly from the query, you can do the following
List<CarView> cars = (from c in db.Cars.Include("Engine.Name") select new CarView() { ID = c.ID, Name = c.Name, EngineName = c.Engine.Name }).ToList();

Resources