Data Annotation for a model consisting of multiple tables in database - asp.net-mvc-4

I have a form displaying fields from 2 tables in database.
I want to validate this form using Data Annotation model validation technique in MVC4.
I am confused whether Data Annotation validation attributes should be applied to individual models(tables) or should I create separate model consisting of fields from both tables.

You should create a new model containing the information you want to display on your view. This specific model has a name: it's called view model. You should always pass view models to your views from the controller actions and your controller actions should always take view models as parameters. Then you could decorate the properties on this view model with validation attributes.

You can do both things. You can decorate your domain model classes and view models. Both things are correct. The thing is that for your view, it's better to use a view model instead of model classes. No need to expose the whole domain model in you view
Just add using System.ComponentModel.DataAnnotations;namespace and add the attributes you need on each property.
For example:
public class BankAccount
{
[Required]
public Person Person { get; set; }
[Required]
public AccountType AccountType { get; set; }
[Required, StringLength(256)]
public string BankName { get; set; }
}

Related

One controller/view for entities with same properties? (DRY code)

We have quite a few lookup entities that all have the same structure - just ID and Name. For example, Gender, Ethnicity are just dropdown lists on a Patient view. Each lookup entity has views for viewing/adding/editing the values. Each entity has its own controller with nearly identical actions - Index (view list), Create, and Edit. The only thing different is the type.
Is there a way to create one controller and one set of views to manage all of these lookup entities using generics, a base entity, some other technique or a combination of these?
One simple thing you can do is create an Interface for ID and Name. Then inherit it in the models that you need to.
Example
public interface IEntity
{
int Id { get; set; }
string Name { get; set; }
}
Inherit this in your models
public class Gender : IEntity
{
}

Pattern for passing common data to _layout.cshtml in MVC4.5

I am trying to come up with the best pattern for passing data to my _layout.cshtml page.
I am toying with creating a common base class from which all view specific models derive. This base class would be recognized by my _layout.cshtml and used to fill in details about the user and load proper images in the header, etc. For example, here is a snippet of it.
public abstract class ViewModelBase
{
public string Username { get; set; }
public string Version { get; set; }
}
At the top of my _layout.cshtml I have...
#model MyProject.Web.Controllers.ViewModelBase
I need a common area to hydrate the information required by the model, and am planning to use the following pattern...
Each action method creates and hydrates a model derived from
ViewModelBase.
The action completes.
I create a ActionFilterAttribute and override OnActionExecuted to cast the
current Result to ViewModelBase.
If the conversion is successful, then I populate the ViewModelBase details with the relevant data.
Here are my questions...
Is the use of a ActionFilterAttribute (OnActionExecuted) a good pattern for what I am trying to do?
I am not able to see how to get the Result created in the action from the HttpActionExecutedContext. How is this done?
I follow the same approach and use a base ViewModel class which all my other viewModels inherit from.
Then, I have a base controller that all controller inherit from. In there, I have one method that takes care of initializing the view model:
protected T CreateViewModel<T>() where T : ViewModel.BaseViewModel, new()
{
var viewModelT = new T {
HeaderTitle = "Welcome to my domain",
VisitorUsername = this.VisitorUsername,
IsCurrentVisitorAuthenticated = this.IsCurrentVisitorAuthenticated,
//...
};
return viewModelT;
}
Then on each controller, when I want to create the view model, I simply call the base controller's method:
var vm = base.CreateViewModel<MyPageCustomViewModel>();

Mvc rules and concepts

A view can have only one #model Folder.ModelName but what if I want to show data from two different tables in one view? How should I do this and what is the right way? For example, if I want to select all profits of the current user and to select all costs of the current user in the one view, then obviously this is 2 tables with 2 different models. Basically my question is, where can I find some rules and concepts for the asp.net mvc pattern?
You would create something known as ViewModel. ViewModel can contain one or more entities, methods, additional fields, etc. You then pass this ViewModel to your View. For example,
namespace Sample
{
public class ProfitCostViewModel
{
public Profit Profit { get; set; }
public Cost Cost { get; set; }
public decimal DoSomeCalculations()
{
// Do something
}
}
}
In your Action, create an instance of this ViewModel class and initialize properties Profit and Cost. Then pass this object to the View. Inside of your view your can declare model like:
#model Sample.ProfitCostViewModel
and use it as
<p>Current profit or something: #Model.Profit.SomeProfitProperty</p>
<p>Sample cost: #Model.Profit.SomeCostProperty</p>
And that's how you would pass two or more entities as a model to your view.
UPDATE: You action could be something like:
public ActionResult YourAction()
{
var profitCostVm = new ProfitCostViewModel();
profitCostVm.Profit = LoadProfitFromSomewhere();
profitCostCm.Cost = LoadCostFromSomewhere();
return View(profitCostCm);
}

Problems with EF-Agnostic design consumed by WCF service.

I am trying to set up EF to work on WCF and keeping the domain class models EF Agnostic.
The code is organized into 3 projects. (I am taking a stab a DDD - I am very new to it but am looking forward t learning more)
Project: QA - Domain Layer. Contains the DataContract models/entities.
References
QA.Data
Project: QA.Data - Data Layer. Contains the context and EDMX (code generation stragtegy = "none")
References
Entity Framework/System.Data.Entity
Project: QA.Repository - Data Access/Repository. Contains the repository classes
References
QA [Domain Layer]
QA.Data [Data Layer]
Entity Frame/System.DataEntity
My understanding is that the domain layer can reference the data layer but the data layer should never reference the domain. The problem that this presents is that my Domain Models/Classes are defined in the Domain layer but the Context which creates and returns them is in the Data layer. In order for my context to know to return a "Widget" object it would need a reference to the Domain layer which defined the "Widget"
My (failed) solution : My solution was to create interfaces for each Domain Model and place them in the data layer. The context would return ... IdbSet ... These interfaces would, in turn, be implemented by the Domain Models, therefore keeping my data layer from directly needing to reference my domain (which causes illegal circular references anyway). The domain models were originally contructed using "ADO.NET DbContext Generator w/WCF Support" T4 templates. This process resulted in the inclusion of the [KnownType(typeof(IWidgetPiece))] at the beginning of of the widget class defin ition. (A Widget has a navigation property ... ICollection ...)
The problem appears when I attempt to access the service, I get the following error
'QA.Data.IWidgetPiece' cannot be added to list of known types since
another type 'System.Object' with the same data contract name
'http://www.w3.org/2001/XMLSchema:anyType' is already present. If
there are different collections of a particular type - for example,
List and Test[], they cannot both be added as known types.
Consider specifying only one of these types for addition to the known
types list.
I can change these to the concrete implementations ... [KnownType(typeof(WidgetPiece))] ... but I continue to get this error because the navigation property they are referring to is still returning an IWidgetPiece interface type which it MUST do in order to satify the interface implementation.
I am trying to figure out how to keep things appropriately divided and still have the context returning what it should. the context returning Interfaces still doesn't "sit" right with me for this and other reasons but I cannot think of another way to do this, and even this is presenting the aforementioned issue. HELP!
Some code to hopefully clarify my previous ramblings ...
namespace QA.Data
{
public interface IWidgetPiece
{
String ID { get; set; }
}
public interface IWidget
{
String ID { get; set; }
ICollection<IWidgetPiece> Pieces;
}
public partial class WidgetEntities : DbContext
{
IDbSet<IWidget> Widgets { get; set; }
IDbSet<IWidgetPiece> WidgetPieces { get; set; }
}
}
namespace QA
{
[KnownType(typeof(IWidgetPiece))]
// [KnownType(typeof(WidgetPiece))]
[DataContract(IsReference = true)]
public partial class Widget : QA.Data.IWidget
{
[DataMember]
public String ID { get; set; }
[DataMember]
public virtual ICollection<IWidgetPiece> Pieces { get; set; }
}
[DataContract(IsReference = true)]
public partial class WidgetPiece : QA.Data.IWidgetPiece
{
[DataMember]
public string ID { get; set; }
}
}
namespace QA.Repository
{
public class WidgetRepository
{
public List<Widget> GetWidgetbyID(String sId)
{
WidgetEntities context = new WidgetEntities();
List<IWidget> objs = context.Widgets.Where(b => b.ID == "78").ToList();
List<Widget> widgetList = new List<Widget>();
foreach (var iwidget in widgetList)
widgetList((Widget)iwidget);
return widgetList;
}
}
}
Do you really want / need two separate models i.e. your data access layer model (edmx) and your "real" domain model? The whole point of an ORM framework like EF is so you can map your domain model to your database tables, using mappings between the physical (database) conceptual model.
Since EF4.1, you can construct your domain model and then in your data access layer map that to your database directly using a fluent API. You can also elect to reverse-engineer your POCO domain model from a database if you want to quickly get up an running.
It just seems a bit of unnecessary complexity to create an entire EF class model, only to then have to map it again into another class model (which will most likely be fairly close to the EF-generated one).

How to simply map an NHibernate ISet to IList using AutoMapper

I'm trying to use AutoMapper to map from DTO's to my Domain.
My DTO's might look like this:
public class MyDTO
{
public string Name { get; set; }
public bool OtherProperty { get; set; }
public ChildDTO[] Children { get; set;}
}
public class ChildDTO
{
public string OtherName { get; set; }
}
My Domain objects like this:
public class MyDomain
{
public string Name { get; set; }
public bool OtherProperty { get; set; }
public ISet<ChildDomain> Children { get; set; }
}
public class ChildDomain
{
public string OtherName { get; set; }
}
How would I setup AutoMapper to be able to map from these Array's to Set's. It seems like AutoMapper is taking the Array's and converting them into IList's then failing on conversion to ISet.
Here's the exception
Unable to cast object of type 'System.Collections.Generic.List`1[DataTranser.ChildDTO]' to type 'Iesi.Collections.Generic.ISet`1[Domain.ChildDomain]'.
I'm hoping to find a simple generic way to do this so that I can minimize the infrastructure needed to map from DTO's to Domain. Any help is greatly appreciated.
UPDATE:
So then how would I model MyDomain -> ChildDomain without ending up with an anemic domain model? I understand that without business logic in MyDomain or ChildDomain the domain model is currently anemic, but the goal was to add business logic in as we move forward. I just want to ensure that my View Model can be translated into the domain model and persisted.
What would you suggest for this scenario, moving from a simple mapping between view and domain and later adding in business rules?
Thanks again for your help.
If your persistence layer is simple, using UseDestinationValue() will tell AutoMapper to not replace the underlying collection:
ForMember(dest => dest.Children, opt => opt.UseDestinationValue())
However, if it's not simple, we just do the updating manually back into the domain. The logic generally gets more complex to update the domain model. Doing reverse mapping puts constraints on the shape of your domain model, which you might not want.
The answer:
You have to create your own IObjectMapper to map a custom collection like ISet
Create your own configuration instance with all the standard
objectmappers and your new
setobjectmapper.
Use an IMappingEngine instance created with the configuration with
your own objectmapper instead of the
static AutoMapper.Mapper class.
Some remarks:
It's easy to configure the IMappingEngine construction in a inversion of control container.
The source of automapper itself might help you with creating the IObjectMapper implementation.
You are using automapper on the opposite way for what it is designed for: It's designed to map complex objects to simple objects. You try to map a simple DTO to a complex entity. (This does not mean that what you want is hard to do with automapper, but you might get different problems in the future)
You are using the anemic domain model anti pattern. Domain should hold all the business logic, so it should not expose a complex collection like ISet (and no public setters for collections at all)