Where to put the save/pre save methods in a domain object? - oop

I want to enforce some rules every time a domain object is saved but i don't know the best way to achieve this. As, i see it, i have two options: add a save method to the domain object, or handle the rules before saving in the application layer. See code sample below:
using System;
namespace Test
{
public interface IEmployeeDAL
{
void Save(Employee employee);
Employee GetById(int id);
}
public class EmployeeDALStub : IEmployeeDAL
{
public void Save(Employee employee)
{
}
public Employee GetById(int id)
{
return new Employee();
}
}
public interface IPermissionChecker
{
bool IsAllowedToSave(string user);
}
public class PermissionCheckerStub : IPermissionChecker
{
public bool IsAllowedToSave(string user)
{
return false;
}
}
public class Employee
{
public virtual IEmployeeDAL EmployeeDAL { get; set; }
public virtual IPermissionChecker PermissionChecker { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public void Save()
{
if (PermissionChecker.IsAllowedToSave("the user")) // Should this be called within EmployeeDAL?
EmployeeDAL.Save(this);
else
throw new Exception("User not permitted to save.");
}
}
public class ApplicationLayerOption1
{
public virtual IEmployeeDAL EmployeeDAL { get; set; }
public virtual IPermissionChecker PermissionChecker { get; set; }
public ApplicationLayerOption1()
{
//set dependencies
EmployeeDAL = new EmployeeDALStub();
PermissionChecker = new PermissionCheckerStub();
}
public void UnitOfWork()
{
Employee employee = EmployeeDAL.GetById(1);
//set employee dependencies (it doesn't seem correct to set these in the DAL);
employee.EmployeeDAL = EmployeeDAL;
employee.PermissionChecker = PermissionChecker;
//do something with the employee object
//.....
employee.Save();
}
}
public class ApplicationLayerOption2
{
public virtual IEmployeeDAL EmployeeDAL { get; set; }
public virtual IPermissionChecker PermissionChecker { get; set; }
public ApplicationLayerOption2()
{
//set dependencies
EmployeeDAL = new EmployeeDALStub();
PermissionChecker = new PermissionCheckerStub();
}
public void UnitOfWork()
{
Employee employee = EmployeeDAL.GetById(1);
//do something with the employee object
//.....
SaveEmployee(employee);
}
public void SaveEmployee(Employee employee)
{
if (PermissionChecker.IsAllowedToSave("the user")) // Should this be called within EmployeeDAL?
EmployeeDAL.Save(employee);
else
throw new Exception("User not permitted to save.");
}
}
}
What do you do in this situation?

I would prefer the second approach where there's a clear separation between concerns. There's a class responsible for the DAL, there's another one responsible for validation and yet another one for orchestrating these.
In your first approach you inject the DAL and the validation into the business entity. Where I could argue if injecting a validator into the entity could be a good practice, injecting the DAL into the business entity is is definitely not a good practive IMHO (but I understand that this is only a demonstration and in a real project you would at least use a service locator for this).

If I had to choose, I'd choose the second option so that my entities were not associated to any DAL infrastructure and purely focused on the domain logic.
However, I don't really like either approach. I prefer taking more of an AOP approach to security & roles by adding attributes to my application service methods.
The other thing I'd change is moving away from the 'CRUD' mindset. You can provide much granular security options if you secure against specific commands/use cases. For example, I'd make it:
public class MyApplicationService
{
[RequiredCommand(EmployeeCommandNames.MakeEmployeeRedundant)]
public MakeEmployeeRedundant(MakeEmployeeRedundantCommand command)
{
using (IUnitOfWork unitOfWork = UnitOfWorkFactory.Create())
{
Employee employee = _employeeRepository.GetById(command.EmployeeId);
employee.MakeRedundant();
_employeeRepository.Save();
}
}
}
public void AssertUserHasCorrectPermission(string requiredCommandName)
{
if (!Thread.CurrentPrincipal.IsInRole(requiredCommandName))
throw new SecurityException(string.Format("User does not have {0} command in their role", requiredCommandName));
}
Where you'd intercept the call to the first method and invoke the second method passing the thing that they must have in their role.
Here's a link on how to use unity for intercepting: http://litemedia.info/aop-in-net-with-unity-interception-model

Where to put the save/pre save methods in a domain object?
Domain objects are persistent-ignorant in DDD. They are unaware of the fact that sometimes they get 'frozen' transported to some storage and then restored. They do not notice that. In other words, domain objects are always in a 'valid' and savable state.
Permission should also be persistent-ignorant and based on domain and Ubiquitous Language, for example:
Only users from Sales group can add OrderLines to an Order in a
Pending state
As opposed to:
Only users from Sales group can save Order.
The code can look like this:
internal class MyApplication {
private IUserContext _userContext;
private ICanCheckPermissions _permissionChecker;
public void AddOrderLine(Product p, int quantity, Money price, ...) {
if(!_permissionChecker.IsAllowedToAddOrderLines(_userContext.CurrentUser)) {
throw new InvalidOperationException(
"User X is not allowed to add order lines to an existing order");
}
// add order lines
}
}

Related

How to migrate a Complex Type to the .net Core Service Implementation

My first time using .net core.
I was able to build a functioning ,net core web application that calls data from my SQL server using Onion Layers. My layout is as below:
Architecture
Core
Application Services
Domain Services
Core.Entity
Infrastructure
UI
API
CemeteryAPI
Web
MVC Web Application
My HomeController has a PageModel with a Complex Type of Search, which consists of about 5 or so ints another 5-6 Lists. In the past I would have done:
var model = new Models.HomePageModel
{
Search = new Business.Search()
};
public partial class Search
{
public String Surname { get; set; }
public String Forename { get; set; }
public String Initials { get; set; }
//etc.
}
I have registered my Services on my startup in ConfigureServices and have attempted to inject this way
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<ICemeteryRepository, CemeteryRepository>();
services.AddScoped<ICountryRepository, CountryRepository>();
//etc
services.AddScoped<ICemeteryService, CemeteryService>();
services.AddScoped<ICountryService, CountryService>();
}
CemeteryService
//ApplicationService
public class CemeteryService : AbstractUnitOfWorkService, ICemeteryService
{
public CemeteryService(IUnitOfWork uow) : base(uow) { }
public int Count()
{
return _unitOfWork.CemeteryRepository.Count();
}
public Cemetery Get(int id)
{
return _unitOfWork.CemeteryRepository.Get(id);
}
public List<Cemetery> List()
{
return _unitOfWork.CemeteryRepository.GetAll().ToList();
}
}
ICemeterRepository
//DomainService
public interface ICemeteryRepository : IRepository<Cemetery>
{
}
CemeteryRepository
public class CemeteryRepository : BaseRepository, ICemeteryRepository
{
public CemeteryRepository(SAWGPDBContext context) : base(context) { }
public int Count()
{
return _context.Cemetery.Count();
}
public Cemetery Get(int id)
{
return _context.Cemetery.Find(id);
}
public IEnumerable<Cemetery> GetAll()
{
return _context.Cemetery;
}
//etc
}
ICemeteryInterface
public interface ICemeteryService
{
int Count();
List<Cemetery> List();
//etc
}
public ActionResult Index([FromServices] ICasualtyService _CasualtyService, IPhotoService _PhotoService, ICountryService _CountryService, ICemeteryService _CemeteryService, IRegimentService _RegimentService)
var model = new Models.HomePageModel
{
Search = new SearchPageModel(_PhotoService, _CasualtyService, _CountryService, _CemeteryService, _RegimentService, )
};
This looked wrong but I couldn't find any proper examples as I wasn't sure what to look for exactly. The above returns
Model bound complex types must not be abstract or value types and must
have a parameterless constructor.
I presume I need to build a SearchService but I'm not entirely clear how to build one for a complex type. Any pointers would be appreciated.

How can I use my database tables etc Users table with ASP.NET Identity?

I have following tables:
Users, Groups, GroupUsers
I have my class like:
public class User
{
List<int> GroupIds;
}
I have a method in my Data Access Layer which returns a user after successful login with the list of all the group ids. How can I override or do something similar in identity to get information from that method?
I have searched the Internet a lot, watched YouTube tutorials, but no one is actually explaining it the way I need it. Can any one help?
First, use claims based security instead of role based: http://visualstudiomagazine.com/articles/2013/08/01/leveraging-claims-based-security-in-aspnet-45.aspx
I've also been retro-fitting an existing SQL based login system to work with identity management. Most of the work you're going to have to do lies within IdentityModel.cs. Specifically how you define ApplicationUser
public class ApplicationUser : IdentityUser<string, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(ApplicationUserManager manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
I've overridden all 4 type parameters on the IdentityUser base class for my implementation, you may not need to do so, depends on how different your retrofit is from how Identity expects things to be.
The other main place you'll most likely have to customize things is within ApplicationDbContext where you'll have to set up where your user, group, and claims/role definitions reside with SQL.
I found these articles on typecastexception to be very useful:
http://typecastexception.com/post/2014/04/20/ASPNET-MVC-and-Identity-20-Understanding-the-Basics.aspx
http://typecastexception.com/post/2014/06/22/ASPNET-Identity-20-Customizing-Users-and-Roles.aspx
http://typecastexception.com/post/2014/04/20/ASPNET-Identity-20-Setting-Up-Account-Validation-and-Two-Factor-Authorization.aspx
http://typecastexception.com/post/2014/07/13/ASPNET-Identity-20-Extending-Identity-Models-and-Using-Integer-Keys-Instead-of-Strings.aspx
Overall there going to be a lot of trial and error in the process as you figure out what pieces of Identity you can utilize as is and where you need to plug in your own code.
Something else you may run into if your passwords aren't stored is having to provide your own implementation of PasswordHasher and plugging that in:
Asp.net Identity password hashing
I did' t get your question, if you want to override you have to mark the method virtual and inherit the class like this:
public class User
{
public virtual void YourMethod()
{
}
}
public class YourClass : User
{
public override void YourMethod()
{
}
}
If you want to separate the class to add some more mothods you can go like this:
partial class User
{
public static void YourMethod()
{
}
}
Create a UserInfo object
public class ApplicationUser : IdentityUser
{
public virtual UserInfo UserInfo { get; set; }
}
public class UserInfo : ComparableEntity
{
public string Email { get; set; }
public string FullName { get; set; }
public string KidName { get; set; }
public string MobilePhone { get; set; }
}
Then create a database context
public class DatabaseContext : IdentityDbContext<ApplicationUser>, IDatabaseContext
{
public IDbSet<UserInfo> UserInfos { get; set; }
}

Return Entity Framework objects over WCF

We have a problem concerning Entity Framework objects and sending them through WCF.
We have a database, and Entity Framework created classes from that database, a 'Wallet' class in this particular situation.
We try to transfer a Wallet using this code:
public Wallet getWallet()
{
Wallet w = new Wallet();
w.name = "myname";
w.walletID = 123;
return w;
}
We need to transfer that Wallet class, but it won't work, we always encounter the same exception:
"An error occurred while receiving the HTTP response to localhost:8860/ComplementaryCoins.svc. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details."
We searched on the internet, and there is a possibility that the error is due to the need of serialization of Entity Framework-objects.
We have absolutely no idea if this could be the case, and if this is the case, how to solve it.
Our DataContract looks like this (very simple):
[DataContract]
public partial class Wallet
{
[DataMember]
public int getwalletID { get { return walletID; } }
[DataMember]
public string getname { get { return name; } }
}
Does anyone ever encountered this problem?
EDIT: Our Entity Framework created class looks like this:
namespace ComplementaryCoins
{
using System;
using System.Collections.Generic;
public partial class Wallet
{
public Wallet()
{
this.Transaction = new HashSet<Transaction>();
this.Transaction1 = new HashSet<Transaction>();
this.User_Wallet = new HashSet<User_Wallet>();
this.Wallet_Item = new HashSet<Wallet_Item>();
}
public int walletID { get; set; }
public string name { get; set; }
public virtual ICollection<Transaction> Transaction { get; set; }
public virtual ICollection<Transaction> Transaction1 { get; set; }
public virtual ICollection<User_Wallet> User_Wallet { get; set; }
public virtual ICollection<Wallet_Item> Wallet_Item { get; set; }
}
}
Thanks for helping us.
I had the same problem some time ago and the solution for this was:
The entity framework was returning a serialized class instead of normal class.
eg. Wallet_asfawfklnaewfklawlfkawlfjlwfejlkef instead of Wallet
To solve that you can add this code:
base.Configuration.ProxyCreationEnabled = false;
in your Context file.
Since the context file is auto generated you can add it in the Context.tt
In the Context.tt file it can be added around lines 55-65:
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
public <#=code.Escape(container)#>()
: base("name=<#=container.Name#>")
{
base.Configuration.ProxyCreationEnabled = false;
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
this.Configuration.LazyLoadingEnabled = false;
<#
Try specifying a setter for the properties, something like this :
[DataContract]
public partial class Wallet
{
[DataMember]
public int getwalletID { get { return walletID; } set { } }
[DataMember]
public string getname { get { return name; } set { } }
}
If it still doesn't work, you may consider creating an intermediate POCO class for this purpose, and use mapper library like AutoMapper or ValueInjecter to transfer the data from the EF objects.
The POCO class should have same properties as your EF class :
[DataContract]
public class WalletDTO
{
[DataMember]
public int walletID { get; set; }
[DataMember]
public string name { get; set; }
}
And modify your method to return this class instead :
public WalletDTO getWallet()
{
Wallet w = new Wallet(); // or get it from db using EF
var dto = new WalletDTO();
//assuming we are using ValueInjecter, this code below will transfer all matched properties from w to dto
dto.InjectFrom(w);
return dto;
}
Are you trying to recieve a IEnumerable<Wallets>? If - yes, please modify your server class that returns the IEnumerable by adding .ToArray() method

Passing parameters to Prism modules

I am storing all my configurations in a module called Congigurations
Something like this:
ConfigurationModule:
[Export(typeof(ConfigurationModule))]
public class ConfigurationModule : NotificationObject
{
public string ConnectionString { get; set; }
}
Now I need to pass some value to ConnectionString from ConfigureAggregateCatalog after the module is beeing loaded.
What is the prism way of doing this, please provide some code.
Thanks in advance:)
I think Prism way is to fill ConnectionString from your ConfigurationModule, not from ConfigureAggregateCatalog. The idea is to separate responsibilities - your ConfigurationModule should load configurations, provide them to another modules and save them back to some repository if needed. Your ConfigureAggregateCatalog should do exactly as it's named - only configure IoC container, nothing more.
UPDATE:
In your scenario I suppose that you have something like AuthenticationModule. So, you can write something like:
[Export]
public class AuthenticationModule
{
[Import]
public ConfigurationModule { get; private set; }
public void OnUserLoggedIn()
{
ConfigurationModule.ConnectionString = "your connection string";
}
}
[Export]
public class AnotherModule
{
[Import]
public ConfigurationModule { get; private set; }
public void DoStuff()
{
if (String.IsNullOrEmpty(ConfigurationModule.ConnectionString))
{
// user isn't logged in
}
var sqlConnection = new SqlConnection(ConfigurationModule.ConnectionString);
}
}

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.