how do i consume model in BL to controller MVC - asp.net-mvc

I am implementing loosely coupled architecture.
MVC as Presentation layer(ProjectName.Web) and all the Business Logic will be handled in a seperate C# project ProjectName.BL.
I will be consuming the webservice from my BL layer(ProjectName.BL). So the requestparameter class objects will be visible to BL since i am making servicereference.
1) The issue i am facing is how will i send my request parameter from Controller to BL layer.
2) Next issue is how will map the ViewModel objects in BL once i get response from service, as the viewmodels are in my web projects.
Request your assistance i have no clue to achieve this one.

This is like any other question on layering and separation of concerns.
Use a DTO. In your Business Layer, introduce types for performing the action you want to perform, and perform mapping between types.
Your question isn't quite concrete, so I'll go with Foo:
Service Layer:
public class ServiceFooRequest
{
public int ID { get; set; }
}
public class ServiceFooResponse
{
public string Bar { get; set; }
}
public ServiceFooResponse GetFoo(ServiceFooRequest request)
{
return new ServiceFooResponse
{
Bar = "Baz"
};
}
Business Layer:
public class BLFooResponse
{
public string Bar { get; set; }
}
public class BLL
{
public BLFooResponse GetFoo(int id)
{
var serviceResponse = _serviceReferenceClient.GetFoo(new ServiceFooRequest
{
ID = id
});
return new BLFooResponse
{
Bar = serviceResponse.Bar
};
}
}
MVC:
public class FooViewModel
{
public string Bar { get; set; }
}
public ActionResult GetFoo(int id)
{
var businessFooResponse = _bll.GetFoo(id);
var fooViewModel = new FooViewModel
{
Bar = businessFooResponse.Bar
};
return View(fooViewModel);
}

You need separate project (DLL) Models. It will store shared between layers models.
Each controller should have reference to BL object or BLL factory.
Hint - use Automapper to copy DAO objects to BDO.
Web project
public class FoodController : BaseController
{
private IFoodBll _foodBll = null;
public FoodController(IFoodBll foodBll)
{
// Make DI of your BLL
_foodBll = foodBll;
}
[HttpPost]
public ActionResult Edit(FoodEditModel model)
{
_foodBll.Save(model);
}
Your Edit.cshtml should look smth like this
#model MyProjects.Web.Models.Foods.FoodEditModel
#Html.HiddenFor(x => Model.Id)
#Html.EditorFor(x => Model.Name)

Related

ASP MVC EF6 Architecture

We have ASP MVC web project. After reading a lot of articles and discussions here in stackoverflow about the correct architechture we have decided to go with the following one, although there is not only one correct way of doing things this is the way we have decided, but we still have some doubts.
We are publishing this here not only to be helped but also to show what we have done in case it is helpful to somebody.
We are working in ASP .NET MVC project, EF6 Code first with MS SQL Server.
We have divided the project into 3 main layers that we have separate into 3 projects: model, service and web.
The model creates the entities and setup the DataContext for the database.
The service make the queries to the data base and transform those entities into DTOs to pass them to the web layer, so the web layer doesn't know anything about the database.
The web uses AutoFac for the DI (dependency Injection) to call the services we have in the service layer and obtain the DTOs to transform those DTOs into Model Views to use them in the Views.
After reading a lot of articles we decided not to implement a repository pattern and unit of work because, in summary, we have read the EF acts as a unit of work itself. So we are simplifying things a little here.
https://cockneycoder.wordpress.com/2013/04/07/why-entity-framework-renders-the-repository-pattern-obsolete/
This is the summary of our project. Now I'm going to go through every project to show the code. We are going to show only a couple of entities, but our project has more than 100 different entities.
MODEL
Data Context
public interface IMyContext
{
IDbSet<Language> Links { get; set; }
IDbSet<Resources> News { get; set; }
...
DbSet<TEntity> Set<TEntity>() where TEntity : class;
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
}
public class MyDataContext : DbContext, IMyContext
{
public MyDataContext() : base("connectionStringName")
{
}
public IDbSet<Language> Links { get; set; }
public IDbSet<Resources> News { get; set; }
...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
}
}
Here is how we declare the entities
public class Link
{
public int Id{ get; set; }
public string Title { get; set; }
public string Url { get; set; }
public bool Active { get; set; }
}
SERVICES
These are the generic classes we use for all the services.
As you see we use the DTOs to get data from the web layer. Also we connect to the database using Dbset = Context.Set()
public interface IService
{
}
public interface IEntityService<TDto> : IService where TDto : class
{
IEnumerable<TDto> GetAll();
void Create(TDto entity);
void Update(TDto entity);
void Delete(TDto entity);
void Add(TDto entity);
void Entry(TDto existingEntity, object updatedEntity);
void Save();
}
public abstract class EntityService<T, TDto> : IEntityService<TDto> where T : class where TDto : class
{
protected IClientContext Context;
protected IDbSet<T> Dbset;
protected EntityService(IClientContext context) { Context = context; Dbset = Context.Set<T>(); }
public virtual IEnumerable<TDto> GetAll()
{
return Mapper.Map<IEnumerable<TDto>>(Dbset.AsEnumerable());
}
public virtual void Create(TDto entity)
{
if (entity == null)
{
throw new ArgumentNullException(nameof(entity));
}
Dbset.Add(Mapper.Map<T>(entity));
Context.SaveChanges();
}
public virtual void Update(TDto entity)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
Context.Entry(entity).State = EntityState.Modified;
Context.SaveChanges();
}
public virtual void Delete(TDto entity)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
Dbset.Remove(Mapper.Map<T>(entity));
Context.SaveChanges();
}
public virtual void Add(TDto entity)
{
Dbset.Add(Mapper.Map<T>(entity));
}
public virtual void Entry(TDto existingEntity, object updatedEntity)
{
Context.Entry(existingEntity).CurrentValues.SetValues(updatedEntity);
}
public virtual void Save()
{
Context.SaveChanges();
}
}
We declare the DTOs in this project (this is a very simple example so we don't have to put all the code here):
public class LinkDto
{
public int Id { get; set; }
public string Title { get; set; }
public string Url { get; set; }
public bool Active { get; set; }
}
Then one of our services:
public interface ILinkService : IEntityService<LinkDto>
{
IPagedList<LinkDto> GetAllLinks(string searchTitle = "", bool searchActive = false, int pageNumber = 1, int pageSize = 10);
LinkDto FindById(int id);
LinkDto Test();
}
public class LinkService : EntityService<Link, LinkDto>, ILinkService
{
public LinkService(IClientContext context) : base(context) { Dbset = context.Set<Link>(); }
public virtual IPagedList<LinkDto> GetAllLinks(bool searchActive = false, int pageNumber = 1, int pageSize = 10)
{
var links = Dbset.Where(p => p.Active).ToPagedList(pageNumber, pageSize);
return links.ToMappedPagedList<Link, LinkDto>();
}
public virtual LinkDto FindById(int id)
{
var link = Dbset.FirstOrDefault(p => p.Id == id);
return Mapper.Map<LinkDto>(link);
}
public LinkDto Test()
{
var list = (from l in Context.Links
from o in Context.Other.Where(p => p.LinkId == l.Id)
select new OtherDto
{ l.Id, l.Title, l.Url, o.Other1... }).ToList();
return list;
}
}
As you see we use AutoMapper (version 5 which has changed a little) to transform from Entities to DTOs the data.
One of the doubts we have is if the use of "Dbset.Find" or "Dbset.FirstOrDefault" is correct and also if the use of "Context.Links" (for any entity).
WEB
FInally the web project where we receive the DTOs and transform those DTOs into ModelViews to show in our views.
We need to call, in the Global.asax Application_Start, AutoFac to do the DI so we can use our services.
protected void Application_Start()
{
...
Dependencies.RegisterDependencies();
AutoMapperBootstrapper.Configuration();
...
}
public class Dependencies
{
public static void RegisterDependencies()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
builder.RegisterModule(new ServiceModule());
builder.RegisterModule(new EfModule());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
public class ServiceModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(Assembly.Load("MyProject.Service")).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces().InstancePerLifetimeScope();
}
}
public class EfModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType(typeof(MyDataContext)).As(typeof(IMyContext)).InstancePerLifetimeScope();
}
}
As you see we also call AutoMapper to configure the different maps.
Then in our controllers we have this.
public class LinksController : Controller
{
private readonly ILinkService _linkService;
public LinksController(ILinkService linkService)
{
_linkService = linkService;
}
public ActionResult Index()
{
var links = _linkService.GetAllLinks();
return View(links.ToMappedPagedList<LinkDto, LinksListModelAdmin>());
}
...
public ActionResult Create(LinksEditModelAdmin insertedModel)
{
try
{
if (!ModelState.IsValid) return View("Create", insertedModel);
var insertedEntity = Mapper.Map<LinkDto>(insertedModel);
_linkService.Create(insertedEntity);
return RedirectToAction("Index");
}
catch (Exception ex)
{
throw ex;
}
}
}
Well, this is it...I hope this can be useful for somebody...and also I hope we can have a little help with the questions we have.
1) Although we are separating database from the web project we do need a reference in the web project to initialize the database and also to inject dependencies, is this correct?
2) Is it correct the approach we have done having our Entities->DTOs->ViewModels? It's a little more work but we have everything separated.
3) In the Service project, when we need to reference a different entity than the main one we are using in the service, is it correct to call Context.Entity?
For example, if we need to retrieve also data from the News entity in the links service, is it correct to call "Context.News.Where..."?
4) We do have a little problem with Automapper and EF proxy, because when we call "Dbset" to retrieve data, it gets a "Dynamic proxies" object so Automapper can't find the proper map so, in order to work, we have to set ProxyCreationEnabled = false in the DataContext definition. This way we can get an Entity in order to map it to the DTO. This disables LazyLoading, which we don't mind, but is this a correct approach or there is a better way to solve this?
Thanks in advance for your comments.
For Question no. 2
Entities->DTOs->ViewModels? is good approach
because you are doing the clean separation, the programmer can work together with ease.
The person who design ViewModels, Views and Controllers don't have to worry about the service layer or the DTO implementation because he will make the mapping when the others developpers finish their implementation.
For Question no. 4
When the flag ProxyCreationEnabled is set to false, the proxy instance will not be created with creating a new instance of an entity. This might not be a problem but we can create a proxy instance using the Create method of DbSet.
using (var Context = new MydbEntities())
{
var student = Context.StudentMasters.Create();
}
The Create method has an overloaded version that accepts a generic type. This can be used to create an instance of a derived type.
using (var Context = new MydbEntities())
{
var student = Context.StudentMasters.Create<Student>();
}
The Create method just creates the instance of the entity type if the proxy type for the entity would have no value (it is nothing to do with a proxy). The Create method does not add or attach the entity with the context object.
Also i read some where if you set ProxyCreationEnabled = false the child element will not loaded for some parent object unless Include method is called on parent object.

Using Viewmodel to populate sql data and add columns

I would like to take a model of a table and make a viewmodel with additions fields, then populate it as a view. How do I do this in the controller? When it was just a model it worked but I'm not sure how to do the same thing when it's a viewmodel. I'm new to asp.net mvc so any help would be appreciated.
Model:
public partial class tblTag
{
public int TagId { get; set; }
public string TagName { get; set; }
}
ViewModel:
public class tblTagViewModel
{
public string TagName { get; set; }
public string TagNameClr
{
get
{
if (TagName == "Test")
{
return "green";
}
else
{
return "red";
}
}
}
}
Controller:
Cannot implicitly convert type 'System.Data.Entity.DbSet<_1MvcSqlServer.Models.tblTag>' to '_1MvcSqlServer.ViewModel.tblTagViewModel'
Now that it's a viewmodel the structure from entities is different, I assume that is the problem. How do I resolve this?
private testEntities db = new testEntities();
public ActionResult Test()
{
ViewModel.tblTagViewModel model = new ViewModel.tblTagViewModel();
model = db.tblTags;
return(model);
}
Here is what I ended up with to get it to work. Is this the correct method?
public ActionResult Test()
{
List<ViewModel.tblTagViewModel> list = new List<ViewModel.tblTagViewModel>();
var model = new ViewModel.tblTagViewModel();
foreach(tblTag p in db.tblTags)
{
ViewModel.tblTagViewModel nw = new ViewModel.tblTagViewModel();
nw.TagName = p.TagName;
list.Add(nw);
}
return View(list);
}
Correct method - create Business layer, which would get data from DB layer and pass this data to View layer (and vice versa, get data from View layer and pass to DB layer).
Also, I recommend to look at IoC (DI) approach :
Business Layer:
First at all, you create new ClassLibrary project and create Business layer POCO classes and an abstraction of your repository:
/// <summary>
/// this is a Business layer class, which is very similar on EF class
/// </summary>
public class Tag
{
public int TagId { get; set; }
public string TagName { get; set; }
}
public interface IRepository
{
List<Tag> GetTagList();
}
Then you create Service:
public class Service
{
private readonly IRepository _repository;
public Service(IRepository repository)
{
if (repository == null)
throw new ArgumentNullException("repository");
_repository = repository;
}
public List<Tag> GetTagList()
{
return _repository.GetTagList();
}
}
on this stage you have compiled version of Business layer. You can add all complex logic of your application and test it. Attent, without DB amd View parts!
Next step - create DB layer
DB Layer:
Create one more Class Library in your solution, add link to BL project and add code like this:
public class EFRepository : IRepository
{
private ... _db;
public EFRepository()
{
.....
}
public List<Tag> GetTagList()
{
var tags = (from i in _db.tblTags select new Tag { TagId = i.TagId, TagName = i.TagName }).ToList();
}
}
so, you have DB and BL layers. And your BL layer is not depend on DB layer, vice versa, DB layer is depend on BL layer .And it's a correct approach, business logic of your application should not be depended on DB!
The last step - View Layer.
View Layer
You can separate View Layer to different project too. I do it inside my ASP.NET MVC application. Add references to DB and BL projects
public class tblTagViewModel
{
public string TagName { get; set; }
public string TagNameClr
{
get
{
if (TagName == "Test")
{
return "green";
}
else
{
return "red";
}
}
}
}
and your controller:
public class HomeController : Controller
{
private readonly Service _service;
public HomeController(IRepository repository)
{
if (repository == null)
throw new ArgumentNullException("repository");
_service = new Service(repository);
}
public ActionResult Test()
{
List<ViewModel.tblTagViewModel> list = new List<ViewModel.tblTagViewModel>();
vat taglist = _service.GetTagList();
foreach (tblTag p in taglist)
{
ViewModel.tblTagViewModel nw = new ViewModel.tblTagViewModel();
nw.TagName = p.TagName;
list.Add(nw);
}
return View(list);
}
}
and, the last step, set DB implementation to your web app:
public class MyControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
var efRepository = new EFRepository();
if (controllerType == typeof(HomeController))
{
return new HomeController(efRepository );
}
return base.GetControllerInstance(requestContext, controllerType);
}
pay attention, that your web-application is not depend on DB layer, it depends only on BL layer (this is logical too). Only one place to set EFRepository in your web application - in controller factory.
With this approach you can easily change EFRepository to another implementation of IRepository, with different DB or even fake DB. You can test any part of your application without unnecessary relationships. You have strong and correct architecture, where your application depend on business logic layer and not depend on DB layer etc. Any changes in DB layer or View layer are not affect on logic layer
For mapping similar POCO classes (i.e BL and DB, BL and View classes) with many properties you can user Automapper

MVC 6 - ViewModel Builder Concept

I started refactoring an ASP.Net 5 web application which uses MVC 6 and Entity Framework 7 when I was wondering about some points. My controllers currently use the DbContext implementation via dependency injection to fill the view models and return them for rendering with the view. Like:
public class UserController : Controller
{
[FromServices]
public MyContext myContext { get; set; }
//route which renders all users
public IActionResult Index()
{
var users = myContext.User.OrderBy(u => u.Name);
List<UserIndexViewModel> v = new List<UserIndexViewModel>();
foreach (var item in users)
{
v.Add(new UserIndexViewModel { Name = item.Name, City = item.City, DateOfBirth = item.DateOfBirth });
}
return View(v);
}
//route to edit user
public async Task<ActionResult> Edit(int id)
{
User user = await FindUserAsync(id);
UserEditViewModel v = new UserEditViewModel { Name = user.Name, City = user.City };
return View(v);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Update(int id, UserEditViewModel userModel)
{
User user = await FindUserAsync(id);
try
{
user.Name = userModel.Name;
user.City = userModel.City;
myContext.User.Attach(user);
myContext.Entry(user).State = EntityState.Modified;
await myContext.SaveChangesAsync();
return RedirectToAction("Index");
}
catch (Exception)
{
ModelState.AddModelError(string.Empty, "Unable to save changes.");
}
return View(userModel);
}
private Task<User> FindUserAsync(int id)
{
return myContext.User.SingleOrDefaultAsync(u => u.UserId == id);
}
}
I did some research and I found some blog posts (like this) which asks to keep controllers clean. Ok.. why not?
I started creating a kind of view model builder to put the logic out of the controller methods over to the view model builder. In the above linked article is a hint to create for each view model a own view-model-builder class - which makes sense in my eyes.
For the model User exist two views and thus two view models (UserIndexViewModel and UserEditViewModel). When I create the related view-model-builder classes they should derivate from the same (abstract) class because it could be that both child classes needs a helper method (like FindUserAsync() - it is not the case in my example but just imagine). So I would have a construct like the following:
public interface IViewModelBuilder<TController, TViewModel>
{
TViewModel Build(TController controller, TViewModel viewModel);
Task<TViewModel > BuildAsync(TController controller, TViewModel viewModel);
}
public abstract class UserViewModelBuilder<TViewModel> : IViewModelBuilder<UserController, TViewModel> { ... }
public class UserIndexViewModelBuilder : SiteViewModelBuilder<UserIndexViewModel> { ... }
public class UserEditViewModelBuilder : SiteViewModelBuilder<UserEditViewModel> { ... }
This mentioned function which is needed by multiple view model builders of one model should be implemented in the abstract class (UserViewModelBuilder in my case), right?
I did it like this:
public abstract class UserViewModelBuilder<TViewModel> : IViewModelBuilder<UserController, TViewModel>
{
[FromServices]
public MyContext myContext { get; set; }
public abstract TViewModel Build(UserController controller, TViewModel viewModel);
public abstract Task<TViewModel> BuildAsync(UserController controller, TViewModel viewModel);
public Task<User> FindUserAsync(int id)
{
return myContext.User.SingleOrDefaultAsync(u => u.UserId == id);
}
}
So with this abstract class I can create the implementation of UserIndexViewModelBuilder and UserEditViewModelBuilder classes as well as for example UserDeleteViewModelBuilder and UserCreateViewModelBuilder classes in future...
Now the question:
Is this a right approach to separate the logic from the controller? If yes, do I need a kind of factory for all view model builders which can be accessed via DI in all my controllers? If it is the way which is kind of best practice for MVC applications. Is there something different to the mentioned guide which can/should be used in MVC 6 apps?
Is the abstract class the right place to call the DbContext implementation via DI? It feels not good for me.
Some other points which I missed? Some if-statements for checking response were removed from the UserController snipped for better readability.
Thank you! :-)

How do I pass an object into the constructor of my VIewModel? ASP.NET MVC 3, Ninject

I've been using the repository pattern described in Bob Cravens blog to create my application, but I'm a bit new and still finding my way around it. I want to inject my DataService object into the constructor of my ViewModel so I can create a SelectList object, and create a drop down box in my view. However I can't seem to get the bindings to work, every time I create the ViewModel it looks for / executes the parameterless constructor! I've tried various ways using answers here on SO but to no avail. Help would be greatly appreciated.
ViewModel:
public class ServerCreateViewModel
{
public SelectList Companies { get; private set; }
public ServerCreateViewModel()
{
}
public ServerCreateViewModel(DataService _dataService)
{
Companies = new SelectList(_dataService.Companies.All(), "Id", "CompanyName");
}
Ninject module:
Bind<DataService>().ToSelf()
.InRequestScope();
var _dataService = Kernel.Get<DataService>();
Bind<ServerCreateViewModel>()
.ToSelf()
.WithConstructorArgument("_dataService", _dataService);
//Bind<ServerCreateViewModel>()
// .ToSelf()
// .WithConstructorArgument("_dataService", ctx => ctx.Kernel.Get<DataService>());
Controller:
public ActionResult Create(ServerCreateViewModel viewModel)
{
return View(viewModel);
}
You shouldn't be doing that!
View Models (all models, in fact) should be just buckets with some data. They should not depend on any business logic, services, etc.
It is controller's responsibility to populate models and pass them to views.
public class ServerCreateViewModel
{
public SelectList Companies { get; private set; }
}
public ActionResult Create()
{
var viewModel = new ServerCreateViewModel
{
Companies = new SelectList(_dataService.Companies.All(), "Id", "CompanyName")
};
return View(viewModel);
}
DataService should be injected into the controller, not view model.

What approach to take for testing AutoMapper configuration in an ASP.NET MVC application?

We are using AutoMapper extensively in our ASP.NET MVC web applications with the AutoMapViewResult approach set out in this question. So we have actions that look like this:
public ActionResult Edit(User item)
{
return AutoMapView<UserEditModel>(View(item));
}
This creates hidden failure points in the application if the requested mapping has not been configured - in that this is not a compile time fail.
I'm looking at putting something in place to test these mappings. As this needs to test the actual AutoMapper configuration I presume this should be done as part of integration testing? Should these tests be structured per controller or per entity? What about the possibility of automatically parsing all calls to AutoMapView?
Note that we are already testing that the AutoMapper configuration is valid using AssertConfigurationIsValid, it is missing mappings that I want to deal with.
If your controller action looked like this:
public AutoMapView<UserEditModel> Edit(User item)
{
return AutoMapView<UserEditModel>(View(item));
}
Then you can pretty easily, using reflection, look for all controller actions in your project. You then examine the action parameter types and the generic type parameter of your AutoMapView action result. Finally, you ask AutoMapper if it has a type map for those input/output models. AutoMapper doesn't have a "CanMap" method, but you can use the IConfigurationProvider methods of FindTypeMapFor:
((IConfigurationProvider) Mapper.Configuration).FindTypeMapFor(null, typeof(User), typeof(UserEditModel);
Just make sure that's not null.
[Test]
public void MapperConfiguration()
{
var mapper = Web.Dto.Mapper.Instance;
AutoMapper.Mapper.AssertConfigurationIsValid();
}
You can use the AssertConfigurationIsValid method. Details are on the automapper codeplex site (http://automapper.codeplex.com/wikipage?title=Configuration%20Validation)
Strictly speaking you should be writing a test to validate the mapping before you write a controller action that depends on the mapping configuration being present.
Either way, you can use the Test Helpers in the MvcContrib project to check the action method returns the expected ViewResult and Model.
Here's an example:
pageController.Page("test-page")
.AssertViewRendered()
.WithViewData<PortfolioViewData>()
.Page
.ShouldNotBeNull()
.Title.ShouldEqual("Test Page");
I do something like this.
using System.Linq;
using System.Reflection;
using AutoMapper;
using Microsoft.VisualStudio.TestTools.UnitTesting;
public class SampleDto
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Sample
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string LoginId { get; set; }
}
public class AutomapperConfig
{
public static void Configure()
{
Mapper.Initialize(cfg => cfg.AddProfile<ViewModelProfile>());
}
}
public class ViewModelProfile : Profile
{
protected override void Configure()
{
CreateMap<SampleDto, Sample>();
}
}
[TestClass]
public class AutoMapperTestsSample
{
public AutoMapperTestsSample()
{
AutomapperConfig.Configure();
}
[TestMethod]
public void TestSampleDtoFirstName()
{
#region Arrange
var source = new SampleDto();
source.FirstName = "Jim";
//source.LastName = "Bob";
var dest = new Sample();
dest.FirstName = "FirstName";
dest.LastName = "LastName";
dest.LoginId = "LoginId";
#endregion Arrange
#region Act
AutoMapper.Mapper.Map(source, dest);
#endregion Act
#region Assert
Assert.AreEqual("Jim", dest.FirstName);
Assert.AreEqual(null, dest.LastName);
Assert.AreEqual("LoginId", dest.LoginId);
#endregion Assert
}
[TestMethod]
public void TestSampleDtoLastName()
{
#region Arrange
var source = new SampleDto();
//source.FirstName = "Jim";
source.LastName = "Bob";
var dest = new Sample();
dest.FirstName = "FirstName";
dest.LastName = "LastName";
dest.LoginId = "LoginId";
#endregion Arrange
#region Act
AutoMapper.Mapper.Map(source, dest);
#endregion Act
#region Assert
Assert.AreEqual(null, dest.FirstName);
Assert.AreEqual("Bob", dest.LastName);
Assert.AreEqual("LoginId", dest.LoginId);
#endregion Assert
}
/// <summary>
/// This lets me know if something changed in the Dto object so I know to adjust my tests
/// </summary>
[TestMethod]
public void TestSampleDtoReflection()
{
#region Arrange
var xxx = typeof(SampleDto);
#endregion Arrange
#region Act
#endregion Act
#region Assert
Assert.AreEqual(2, xxx.GetRuntimeFields().Count());
Assert.AreEqual("System.String", xxx.GetRuntimeFields().Single(a => a.Name.Contains("FirstName")).FieldType.ToString());
Assert.AreEqual("System.String", xxx.GetRuntimeFields().Single(a => a.Name.Contains("LastName")).FieldType.ToString());
#endregion Assert
}
}

Resources