A way to always filter query results with Entity Framework Core - asp.net-core

I am using an OrgID on all my models in an ASP.NET application using EF as a way to partition the database. I do this so that the database can be shared among multiple users while ensuring that only the data of their organization is available to them.
This forces me to write this OrgID with every insert and to filter every call I make to the database.
So for instance I query the current user's OrgID and insert this in my controllers' Update methods like this:
store.OrgID = await _userManager.GetUserAsync(User).OrgID;
_context.Update(store);
await _context.SaveChangesAsync();
Then when I want to list out objects I again need to filter by OrgID:
var orgID = await _userManager.GetUserAsync(User).OrgID;
var stores = await _context.Stores.Where(s => s.OrgID == orgID).ToListAsync();
I'd love to find a way to override the ApplicationDBContext so that these are handled automatically otherwise it's quite a tedious and error prone task to always handle this in every call to the database.
Any suggestions would be greatly appreciated.

Check Global Query Filters.
Global query filters are LINQ query predicates (a boolean expression
typically passed to the LINQ Where query operator) applied to Entity
Types in the metadata model (usually in OnModelCreating). Such filters
are automatically applied to any LINQ queries involving those Entity
Types, including Entity Types referenced indirectly, such as through
the use of Include or direct navigation property references.

Create an interface that has the OrgID :
public interface IOrgID
{
public int OrgID { get; set; }
}
All your models must implement this interface e.g.:
public class ApplicationUser : IdentityUser, IOrgID
{
public int OrgID { get; set; }
//...
}
public class Stores : IOrgID
{
public int OrgID { get; set; }
//...
}
Use generic repository and create CRUD methods considering the OrgID from the currently logged in user:
public class MyRepo
{
private readonly ApplicationDbContext _context;
private readonly IHttpContextAccessor _accessor;
private readonly int _orgID;
public MyRepo(ApplicationDbContext context, IHttpContextAccessor accessor)
{
_context = context;
_accessor = accessor;
var userId = _accessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
_orgID = _context.Users.Find(userId).OrgID;
}
public async Task<T> GetAsync<T>(Expression<Func<T, bool>> whereExp)
where T : class, IOrgId
{
return await _context.Set<T>().Where(x => x.OrgId == _orgID).FirstOrDefaultAsync(whereExp);
}
public async Task<bool> Create<T>(T entitiy)
where T : class, IOrgId
{
_context.Set<T>().Add(entitiy);
return await _context.SaveChangesAsync() > 0;
}
public async Task<bool> UpdateAsync<T>(T entity)
where T : class, IOrgId
{
_context.Entry<T>(entity).State = EntityState.Modified;
return await _context.SaveChangesAsync() > 0;
}
public async Task<IEnumerable<T>> ListAsync<T>(Expression<Func<T, bool>> whereExp)
where T : class, IOrgId
{
return await _context.Set<T>().AsNoTracking().Where(x => x.OrgId == _orgID).Where(whereExp).ToListAsync();
}
public async Task<bool> DeleteAync<T>(T entity)
where T : class, IOrgId
{
_context.Entry<T>(entity).State = EntityState.Deleted;
return await _context.SaveChangesAsync() > 0;
}
}

What people do I this case is create a class wrapping the DbContext and exposing methods that make sense for their business logic. In your case you can make a UserRepository/StoreRepository classes where the search methods require a origID paramamter
public class StoreRepository {
private ApplicationDBContext _context
StoreRepository(ApplicationDBContext context){
_context = context
}
public Task<Ilist<Store>> GetStores(int origID){
return _context.Stores.Where(s => s.OrgID == orgID).ToListAsync();
}
}

Related

.NET Core 3.1 Complex Session Wrapper Not Working

I am trying to create a complex session wrapper in .NET Core 3.1. I ran into an issue where my variables are not being set. This is the way I set up the session wrapper class.
public class SessionWrapper : ISessionWrapper
{
private static IHttpContextAccessor context;
public SessionWrapper(IHttpContextAccessor _context)
{
context = _context;
}
public static Course Course
{
get
{
var key = context.HttpContext.Session.GetString("course");
if (key == null)
{
return default;
}
else
{
return JsonConvert.DeserializeObject<Course>(key);
}
}
set
{
if(value != null)
{
context.HttpContext.Session.SetString("course", JsonConvert.SerializeObject(value));
}
}
}
}
I configured my services to use session and the sessionwrapper.
services.AddDistributedMemoryCache();
services.AddSession();
services.AddHttpContextAccessor();
services.AddScoped<ISessionWrapper, SessionWrapper>();
I configured the pipeline to use session
app.UseSession();
In my controller, I am initializing course and set the session wrapper. Then, I am setting the course id to 4. It's not complaining, but the course id is not being set. It's always null. I've been looking at it for so and is getting frustrated. What am I missing here?
Course myCourse = new Course();
SessionWrapper.Course = myCourse;
SessionWrapper.Course.Id = "4"
I feel like your wrapper in itself isn't really the best approach to do this. A self-aware subclass of Course that has the 'know how' to store itself in Session, seems more logical to me. That way you are freeing your controller(s) from the responsibility for managing the persistence.
public abstract class Course
{
public abstract int Id { get; set; }
}
public class SessionCourse : Course
{
private int _id;
public override int Id
{
get => _id;
set { _id = value; UpdateSession(); }
}
// The GetCourse method is a factory for creating the SessionCourse objects
// and providing it with a ISession object so they can store themselves.
public static Course GetCourse(IServiceProvider services)
{
ISession session = services.GetRequiredService<IHttpContextAccessor>()?.HttpContext.Session;
SessionCourse course = session?.GetJson<SessionCourse>("Course") ?? new SessionCourse();
course.Session = session;
return course;
}
[JsonIgnore]
private ISession Session { get; set; }
private void UpdateSession() {
Session.SetJson("Course", this);
}
}
Now the trick is to satisfy requests for the Course object with the SessionCourse object that will store itself in session. You can do that by adding a scoped service with a lambda expression for the course object. The result is that requests for the Course service will return the SessionCourse object.
services.AddScoped<Course>(sp => SessionCourse.GetCourse(sp));
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
So the benefit of creating this kind of service is that it allows you to simplify the controllers where Course objects are used.
public class CourseController : Controller
{
private Course course;
public CartController(Course courseService)
{
course = courseService;
}
public void SetCourseId()
{
course.Id = "4";
}
SessionExtension.cs defines extension methods for adding objects to the session.
public static class SessionExtensions {
public static void SetJson(this ISession session, string key, object value) {
session.SetString(key, JsonConvert.SerializeObject(value));
}
public static T GetJson<T>(this ISession session, string key) {
var sessionData = session.GetString(key);
return sessionData == null ? default(T) : JsonConvert.DeserializeObject<T>(sessionData);
}
}

How can I make an ASP Core Claims Principal available in a non-controller object?

I am working on an ASP Core 2 project using JWT authentication and the Dapper ORM.
Like all ASP projects, I have a lot of controllers, each instantiating its associated data objects. Each data object inherits from an abstract DbObject class that provides database access services. I also have an AuthenticatedUser object that abstracts the JWT to make it's properties easier to use.
What I want is to do is create the AuthenticatedUser object in the constructor of DbObject. Of course, one method is to create it in the controller and pass it to every concrete data object but this is messy as it would have to be passed hundreds of times (and it just feels wrong).
Is there a way to use the ASP Core middleware to get the token after authentication and make it available through dependency injection in the DbObject?
Edit
Hopefully, this clarifies my intentions. I would like the controller to create data objects and use their properties and methods without regard to implementation (i.e. DbObject). But queries executed by DbObject will be filtered by information in the token of the logged in user.
public class ManufacturerController : Controller {
[HttpGet]
public async Task<IActionResult> Get() {
var manufacturers = await new Manufacturer().SelectMany();
return Ok(manufacturers);
}
[HttpGet("{id}")]
public async Task<IActionResult> Get(int id) {
var manufacturer = await new Manufacturer().SelectOne(id);
return Ok(manufacturer);
}...
public class Manufacturer : DbObject<Manufacturer> {
protected override string QrySelectOne => #"
Select *
From org.fn_Manufacturers ({0})
Where Id = {1}";
protected override string QrySelectMany => #"
Select *
From org.fn_Manufacturers ({0})";
public int Id { get; set; }
public string Name { get; set; }
public string Phone { get; set; }...
public abstract class DbObject<T> {
protected readonly AuthenticatedUser authenticatedUser;
public DbObject(IHttpContextAccessor contextAccessor) {
authenticatedUser = new
AuthenticatedUser(contextAccessor.HttpContext.User);
}
protected abstract string QrySelectOne { get; }
protected abstract string QrySelectMany { get; }
public async Task<T> SelectOne (int id) {...}
public async Task<T> SelectOne(params object[] ids) {...}
public async Task<IEnumerable<T>> SelectMany () {...}
public async Task<IEnumerable<T>> SelectMany (params object[] ids) {...}
I suppose one solution may be to create a static data object factory which has the IHttpContextAccessor injected??
ASP.NET Core provides IHttpContextAccessor interface for accessing HttpContext from non-controller objects.
The usage is fair simple. Inject IHttpContextAccessor into DbObject and access HttpContext by calling IHttpContextAccessor.HttpContext:
public abstract class DbObject
{
protected DbObject(IHttpContextAccessor contextAccessor)
{
var context = contextAccessor.HttpContext;
// Create instance of AuthenticatedUser based on context.User or other request data
}
}
EDIT
Your controllers instantiate data objects directly (with new operator), that's why you can't have IHttpContextAccessor injected out of the box. Here are possible solutions. I list them in order of my preference (from best to worst).
If each controller uses only one (or just several) types of data objects, the best options will be to avoid direct instantiation and move toward normal Dependency Injection.
So if ManufacturerController requires only Manufacturer like in your sample then, it's better to inject Manufacturer instance to controller, not to create it inside:
public class Manufacturer1Controller : Controller
{
private readonly Manufacturer manufacturer;
public Manufacturer1Controller(Manufacturer manufacturer)
{
this.manufacturer = manufacturer ?? throw new ArgumentNullException(nameof(manufacturer));
}
[HttpGet]
public async Task<IActionResult> Get()
{
var manufacturers = await manufacturer.SelectMany();
return Ok(manufacturers);
}
// ...
}
IHttpContextAccessor will be injected into Manufacturer and passed to base DbObject:
public class Manufacturer : DbObject<Manufacturer>
{
public Manufacturer(IHttpContextAccessor contextAccessor) : base(contextAccessor)
{
}
}
It's the cleanest solution in the list. You use DI in classic way and utilize all benefits DI provides.
If one controller could use dozens of different data objects, you could inject the factory object that creates instances of data objects. It could be simple implementation based on IServiceProvider:
public interface IDbObjectFactory
{
TDbObject Create<TDbObject>() where TDbObject : DbObject<TDbObject>;
}
public class DbObjectFactory : IDbObjectFactory
{
private readonly IServiceProvider serviceProvider;
public DbObjectFactory(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
}
public TDbObject Create<TDbObject>() where TDbObject : DbObject<TDbObject>
{
return serviceProvider.GetRequiredService<TDbObject>();
}
}
public class Manufacturer2Controller : Controller
{
private readonly IDbObjectFactory dbObjectFactory;
public Manufacturer2Controller(IDbObjectFactory dbObjectFactory)
{
this.dbObjectFactory = dbObjectFactory ?? throw new ArgumentNullException(nameof(dbObjectFactory));
}
[HttpGet]
public async Task<IActionResult> Get()
{
var manufacturer = dbObjectFactory.Create<Manufacturer>();
var manufacturers = await manufacturer.SelectMany();
return Ok(manufacturers);
}
}
The code for Manufacturer and DbObject does not change comparing to the first option.
I don't see any reason not to use option #1 or #2. However just to complete the picture, I'll describe another two options.
Inject IHttpContextAccessor into conroller and pass this instance (or IHttpContextAccessor.HttpContext.User) to Data Object constructor invoked with operator new:
public class Manufacturer3Controller : Controller
{
private readonly IHttpContextAccessor contextAccessor;
public Manufacturer3Controller(IHttpContextAccessor contextAccessor)
{
this.contextAccessor = contextAccessor ?? throw new ArgumentNullException(nameof(contextAccessor));
}
[HttpGet]
public async Task<IActionResult> Get()
{
var manufacturer = await new Manufacturer(contextAccessor).SelectMany();
// or
// var manufacturer = await new Manufacturer(contextAccessor.HttpContext.User).SelectMany();
return Ok(manufacturer);
}
}
It's a bad solution, because you don't use Dependency Injection for Manufacturer here and loose many advantages that DI provides.
And the worst option would be using of static object factory with injected IHttpContextAccessor. With this approach you also loose benefits of DI. In addition you get ugly code somewhere in Startup that initializes static instance of IHttpContextAccessor. When you come to this approach, you'll discover that theere is no quite elegant way to do this.
My advice: use option #1 untill you have good reasons against it. Then use option #2.
Here is Sample Project on GitHub with samples for approaches ##1-3.

Generic authorization with handler

I'm trying to implement authorization in my ASP.NET Core 2.0 Web app.
This app has like 20 models, each with a controller implementing at least a CRUD. I found these two pages and I liked the idea of using a handler to authorize requisitions. I would like initially to implement authorization by user, i.e., a user has only permission to see/edit his own entities. All my database entities have an OwnerId field.
These examples I found seem to only work for one specific controller.
So, my question is: is it possible to create one authorization handler for all controllers?
Have you found a solution or workaround yet that works with the authorization handler or authorization attributes? I have the exact same setup as you do.
I was trying to create a generic attribute to serve all may Entity CRUD owner checks, but generic attributes are not allowed by design.
The only two (unsatisfying) solutions that I came up with are:
Within the controller action, get the ownerId from the User, forward it all the way to your CRUD and include there a check for the ownerId. However, the code must be duplicated for every action in every controller.
[HttpGet("{id}"]
public async Task<IActionResult> GetById(int id)
{
var stringGuid = User.Claims.FirstOrDefault(c => c.Type == "sub")?.Value;
if (String.IsNullOrWhiteSpace(stringGuid)) return Unauthorized();
var ownerGuid = new Guid(stringGuid);
var entity = _yourCrudInstance.GetById(id, ownerGuid);
return Ok(entity);
}
Add a method to your CRUD repository like bool IsOwner(Guid ownerId) and use this method when creating the custom authorization handler (by creating a custom requirement together with a custom handler). This eliminates code duplication in the controller, because you can create a new policy with this custom authorization handler and consequently you can simply decorate every action with a [Authorize(Policy = "yourOwnershipPolicy")]. But still, there must be a service created for each and every controller. Moreover, the IsOwner(...) method adds an additional database call compared to solution 1 - one db call for checking the ownership (during authorization check) and one db call for actually getting the entity (by working through the controller action).
[Authorize(Policy = "yourOwnershipPolicy")]
public async Task<IActionResult> GetById(int id)
{
var entity = _yourCrudInstance.GetById(id);
return Ok(entity);
}
I am going with the first solution until I found a way to create a generic authorization handling for my generic CRUD repository, because one may forget creating the required authorization policy for a new entity, but one cannot forget to supply the parameter ownerId to .GetById(id, ownerGuid), provided there is no overload method, or the code doesn't compile.
Update:
I found a third solution in which was able to create a kind of generic authorization attribute. The trick was to use the type of concrete repository as input parameter in the authorization attribute. Yet, there is still a limitation: The authorization attribute must be copied for every type of Id, for example int Id, Guid id, etc. But still, this reduces repeated code to the types of ids. In most cases, people only have one type of id, probably int or Guid.
Here some code that demonstrates my architecture. It is heavily summarized and redacted, but should compile successfully. My original code is working and in production:
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
[Route("api/yourcontroller")]
public class YourApiController : Controller
{
private readonly YourEntityXYZRepository _repo;
public YourApiController(YourDbContext yourDbContext)
{
_repo = new YourEntityXYZRepository(yourDbContext);
}
[HttpGet("{id}")]
[AuthorizeOwnerIntId(typeof(YourEntityXYZRepository), Policy = "YourCustomPolicy")]
public async Task<IActionResult> GetById(int id)
{
var entity = _repo.GetById(id);
return Ok(entity);
}
}
// The "generic" authorization attribute for type int id
// Similar authorization attributes for every type of id must be created additionally, for example Guid
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class AuthorizeOwnerIntIdAttribute : AuthorizeAttribute, IAuthorizationFilter
{
private object _entityRepositoryObject;
private IAsyncOwnerIntId _entityRepository;
private readonly Type _TCrudRepository;
public AuthorizeOwnerIntIdAttribute(Type TCrudRepository)
{
_TCrudRepository = TCrudRepository;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
var yourDbContext = context.HttpContext.RequestServices.GetService<YourDbContext>();
_entityRepositoryObject = Activator.CreateInstance(_TCrudRepository, yourDbContext);
_entityRepository = _entityRepositoryObject as IAsyncOwnerIntId;
var user = context.HttpContext.User;
if (!user.Identity.IsAuthenticated)
{
// it isn't needed to set unauthorized result
// as the base class already requires the user to be authenticated
// this also makes redirect to a login page work properly
// context.Result = new UnauthorizedResult();
return;
}
// get entityId from uri
var idString = context.RouteData.Values["id"].ToString();
if (!int.TryParse(idString, out var entityId))
{
context.Result = new UnauthorizedResult();
return;
}
// get subjectId from user claims
var ownerIdString = context.HttpContext.User.Claims.FirstOrDefault(c => c.Type == "sub")?.Value;
if (!Guid.TryParse(ownerIdString, out var ownerGuid))
{
context.Result = new UnauthorizedResult();
return;
}
if (!_entityRepository.IsEntityOwner(entityId, ownerGuid))
{
context.Result = new UnauthorizedResult();
}
}
}
// Your concrete repository
public class YourEntityXYZRepository : AsyncCrud<YourEntityXYZ, int>,
IAsyncOwnerIntId // Note that type concrete IAsyncOwnerIntId is only implemented in concrete repository
{
public YourEntityXYZRepository(YourDbContext yourDbContext) : base(yourDbContext)
{
}
}
// Your generic Crud repository
public abstract class AsyncCrud<TEntity, TId> : IAsyncCrud<TEntity, TId>
where TEntity : class, IEntityUniqueIdentifier<TId>, IEntityOwner
where TId : struct
{
protected YourDbContext YourDbContext;
public AsyncCrud(YourDbContext yourDbContext)
{
YourDbContext = yourDbContext;
}
// Note that the following single concrete implementation satisfies both interface members
// bool IsEntityOwner(TId id, Guid ownerGuid); from IAsyncCrud<TEntity, TId> and
// bool IsEntityOwner(int id, Guid ownerGuid); from IAsyncOwnerIntId
public bool IsEntityOwner(TId id, Guid ownerGuid)
{
var entity = YourDbContext.Set<TEntity>().Find(id);
if (entity != null && entity.OwnerGuid == ownerGuid)
{
return true;
}
return false;
}
// Further implementations (redacted)
public Task<bool> SaveContext() { throw new NotImplementedException(); }
public Task<TEntity> Update(TEntity entity){ throw new NotImplementedException(); }
public Task<TEntity> Create(TEntity entity, Guid ownerGuid) { throw new NotImplementedException(); }
public Task<bool> Delete(TId id) { throw new NotImplementedException(); }
public Task<bool> DoesEntityExist(TId id) { throw new NotImplementedException(); }
public virtual Task<TEntity> GetById(TId id) { throw new NotImplementedException(); }
}
// The interface for the Crud operations
public interface IAsyncCrud<TEntity, TId>
where TEntity : class, IEntityUniqueIdentifier<TId>
where TId : struct
{
bool IsEntityOwner(TId id, Guid ownerGuid);
Task<bool> DoesEntityExist(TId id);
Task<TEntity> GetById(TId id);
Task<TEntity> Create(TEntity entity, Guid ownerGuid);
Task<TEntity> Update(TEntity entity);
Task<bool> Delete(TId id);
Task<bool> SaveContext();
}
// The interface for the concrete type method for int id
// Similar interfaces for every type of id must be created additionally, for example Guid
public interface IAsyncOwnerIntId
{
bool IsEntityOwner(int id, Guid ownerGuid);
}
// Typical db context
public class YourDbContext : DbContext
{
public YourDbContext(DbContextOptions<YourDbContext> options) : base(options)
{
}
public DbSet<YourEntityXYZ> YourEntityXYZ { get; set; }
}
public class YourEntityXYZ : IEntityUniqueIdentifier<int>, IEntityOwner
{
public int Id { get; set; }
public Guid? OwnerGuid { get; set; }
// ... Additonal custom properties
}
public interface IEntityUniqueIdentifier<TId>
where TId : struct
{
TId Id { get; set; }
}
public interface IEntityOwner
{
Guid? OwnerGuid { get; set; }
}

NHibernate: How to inject dependency on an entity

NHibernate 3.2/Fluent NHibernate 1.3/StructureMap 2.6.3 -
Trying to follow DDD as an architectural strategy, I typically don't have dependencies on domain entities. However, I'm experimenting right now with adding more behavior to my domain entities so that they are not so anemic. Everything was going well until I hooked up NHibernate. I've got two issues:
NH requires a parameterless constructor and I'd rather not have a
ctor that shouldn't be used.
When NH tries to instantiate my entity, it needs to resolve my
dependencies but I haven't given NH anything with which it can do
that.
I've been reading on the web, but most (if not all) of the examples I have found are outdated (or just old). Even though the NH camp probably doesn't approve of what I'm doing, I'm looking for the NH way to do this.
The solution ended up an implementation of NHibernate's IInterceptor. It is actually a very simple implementation when you inherit from EmptyInterceptor and override JUST the Instantiate() and SetSession() methods. Here's my interceptor using StructureMap:
public class DependencyInjectionEntityInterceptor : EmptyInterceptor
{
IContainer _container;
ISession _session;
public DependencyInjectionEntityInterceptor(IContainer container)
{
_container = container;
}
public override void SetSession(ISession session)
{
_session = session;
}
public override object Instantiate(string clazz, EntityMode entityMode, object id)
{
if (entityMode == EntityMode.Poco)
{
var type = Assembly.GetAssembly(typeof (SomeClass)).GetTypes().FirstOrDefault(x => x.FullName == clazz);
var hasParameters = type.GetConstructors().Any(x => x.GetParameters().Any());
if (type != null && hasParameters)
{
var instance = _container.GetInstance(type);
var md = _session.SessionFactory.GetClassMetadata(clazz);
md.SetIdentifier(instance, id, entityMode);
return instance;
}
}
return base.Instantiate(clazz, entityMode, id);
}
}
Then, all you have to do is tell NHibernate to use your interceptor:
public FluentConfiguration GetFluentConfiguration(IContainer container)
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(c => c.FromConnectionStringWithKey("Database"))
.ShowSql())
.Mappings(m =>
m.AutoMappings.Add(AutoMap.AssemblyOf<SomeClass>()))
.ExposeConfiguration(x =>
x.SetInterceptor(new DependencyInjectionEntityInterceptor(container)));
}
When I was researching this, some suggested passing in the SessionFactory into the ctor of the interceptor class. Honestly, from a session management perspective, this approach would be better.
If you need additional dependencies in your entities don't use constructor injection. Instead create an additional parameter in the entity method.
Now you will ask yourself how do you get the dependency. For this you can use CommandHandlers and Commands. The command handler takes the dependency within its constructor and calls the method of the entity. In the UI you create a command message and send it to a command processor which is responsible for calling the correct command handler.
I hope my explanation is comprehensible to you.
Domain:
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public void SendNotification(string message, INotifier notifier)
{
notifier.SendMessage(string.Format("Message for customer '{0}' ({1}): {2}", Name, Id, message));
}
}
The INotifier infrastructure component is passed through the method and not the constructor!
Infrastructure:
public interface INotifier
{
void SendMessage(string message);
}
class EmailNotifier : INotifier
{
public void SendMessage(string message)
{
// SmtpClient...
}
}
class SMSNotifier : INotifier
{
public void SendMessage(string message)
{
// SMS ...
}
}
Command and CommandHandler:
public class NotificationCommandHandler : ICommandHandler<NotificationCommand>
{
private readonly INotifier _notifier;
public NotificationCommandHandler(INotifier notifier)
{
_notifier = notifier;
}
public void Execute(NotificationCommand commandMessage)
{
commandMessage.Employee.SendNotification(commandMessage.Message, _notifier);
}
}
public class NotificationCommand
{
public string Message { get; set; }
public Employee Employee { get; set; }
}
The CommandHandler gets the INotifier through constructor injection. So you do not need to use your IoC Container like a ServiceLocator.
Usage i.e. in the UI in a controller:
public class Controller
{
private readonly IMessageProcessor _messageProcessor;
public Controller(IMessageProcessor messageProcessor)
{
_messageProcessor = messageProcessor;
}
public void SendNotification (Employee employee, string message)
{
var sendMailCommand = new NotificationCommand
{
Employee = employee,
Message = message
};
_messageProcessor.Process(sendMailCommand);
}
}
If you have questions about the command processor have a look at the mvccontrib project or ask a separate question.
Sorry my previous answer didn't address the specific question. I did some more research, and it looks like I have much more to learn about when and when not to use an anemic domain model. Regarding your question, I found this article to be very on topic. It is on java, not c#, but the principles are the same. Hope this helps.

AutoMapper Update Actions in ASP.NET MVC

This is probably quite straight forward for some, however I'm a bit confused and can't find a decent example. Say I'm using view models and my POST action takes in that view model. Typically I would do something along the following lines:
[HttpPost]
public ActionResult Update(UserViewModel uvm)
{
User user = Mapper.Map<UserViewModel, User>(uvm);
_repository.Update(user);
return RedirectToAction("Index");
}
Although this isn't the full picture. The mapping would work fine, however if I were to just update what I've mapped then it'd get rid of valuable data in the database because of course in this case I'm not updating the password or other details.
My repository looks something like this:
public void Update(User user)
{
User u = Session.QueryOver<User>().Where(x => x.UserName == user.UserName).SingleOrDefault();
if (u == null)
throw new Exception("User not found");
u.Forename = user.Forename;
u.Surname = user.Surname;
u.EmailAddress = user.EmailAddress;
}
[I'm using NHibernate so it'll save the object back to the DB once the session is closed (after the request has finished) automatically for me.]
So my question is, in my repository should I load the "User" entity, then update the values I want, and then save it back, or is there another method to do this? The reason I ask is because it seems a bit... "manual" if you see what I mean? Perhaps it is correct, but I just wanted to see opinions of those with more experience in this area.
Cheers
I use the following approach:
[HttpPost]
public ActionResult Update(UserViewModel uvm)
{
User user = _userRepository.FindById(uvm.Id);
user.Forename = uvm.Forename;
user.Surname = uvm.Surname;
user.EmailAddress = uvm.EmailAddress;
_userRepository.Update(user);
return RedirectToAction("Index");
}
UPDATE:
To address the comments about AutoMapper here's how to proceed:
Let's take for example the following classes:
public class UserViewModel
{
public string Forename { get; set; }
public string Surname { get; set; }
public string EmailAddress { get; set; }
}
public class User
{
public string Forename { get; set; }
public string Surname { get; set; }
public string EmailAddress { get; set; }
public string Password { get; set; }
}
We don't want to modify the user password in the UI. So we express our intention to AutoMapper:
Mapper
.CreateMap<UserViewModel, User>()
.ForMember(dest => dest.Password, opt => opt.Ignore());
and then:
[HttpPost]
public ActionResult Update(UserViewModel uvm)
{
// Fetch the original model we would like to update
User user = _userRepository.FindById(uvm.Id);
Mapper.Map(uvm, user);
// At this stage the user model will have its
// Forename, Surname and EmailAddress properties
// updated from the view model and its Password property
// will remain the one we got from the repository
_userRepository.Update(user);
return RedirectToAction("Index");
}
UPDATE 2:
To address the question in the comments about configuring AutoMapper I usually use Profiles:
public class UsersProfile : Profile
{
protected override void Configure()
{
Mapper
.CreateMap<UserViewModel, User>()
.ForMember(dest => dest.Password, opt => opt.Ignore());
Mapper
.CreateMap<User, UserViewModel>();
}
}
and then have a registry class which registers all the mappers:
public class MappingsRegistry
{
public static void Configure()
{
Mapper.AddProfile(new UsersProfile());
Mapper.AddProfile(new SomeOtherProfile());
...
}
}
which is called in Application_Start:
MappingsRegistry.Configure();
Finally my controllers have a reference to the mapping engine:
public class UsersController : Controller
{
private readonly IUsersRepository _repository;
private readonly IMappingEngine _mappingEngine;
public ContratsFCController(IUsersRepository repository, IMappingEngine mapperEngine)
{
_repository = repository;
_mapperEngine = mapperEngine;
}
[AutoMap(typeof(User), typeof(UserViewModel))]
public ActionResult Update(int id)
{
var user = _repository.FindById(id);
return View(user);
}
[HttpPost]
public ActionResult Update(UserViewModel uvm)
{
if (!ModelState.IsValid)
{
return View(uvm);
}
var user = _repository.FindById(uvm.Id);
_mapperEngine.Map(uvm, user);
_repository.Update(user);
return RedirectToAction("Index");
}
}
Now all that's left is to instruct your DI framework to pass the Mapper.Engine property to the constructor and in your unit tests obviously substitute them with an appropriate mock.