What is the best practice for placing business logic in message based design?
Im using servicestack for building my api.
The wiki shows the example of placing the RequiredRole Attribute on the message instead of the service handling it.
In a sense this [RequiredRole]/[Authenticate] is business logic/security attached to the message.
Concrete example
Say for example i would add DeleteAddress message:
public class DeleteAddress : IReturn<bool>
{
public int AddressId { get; set; }
}
But for this to be properly secure i want to check either Admin Role, permission to ManageAllAddresses or that the AddressId is linked to this user (maybe in session, maybe through a db call).
How would i best go about this?
Proposition
Is the following code the good practice and if so how would i implement it?
[RequiredRole("Admin")]
[RequiredPermission("ManageAllAddresses ")]
[RequiredAddressLinkedToAccount]
public class DeleteAddress : IReturn<bool>
{
public int AddressId { get; set; }
}
ServiceStack's recommendation is to keep your ServiceModel free of dependencies so we'd recommend to annotate your Service implementation classes instead which you can annotate either on the Service class to apply to all Operations or on the individual methods to apply just to that operation, e.g:
[RequiredRole("Admin")]
public class AddressServices : Service
{
[RequiredPermission("ManageAllAddresses ")]
[RequiredAddressLinkedToAccount]
public object Any(DeleteAddress request)
{
}
}
Please note ServiceStack requires your Services to return reference types, which is typically a Response DTO but can also be a string, e.g:
public class DeleteAddress : IReturn<string>
{
public int AddressId { get; set; }
}
To finish of this question. I could make a request filter and add it on the service.
Either inherit from AuthenticateAttribute or Directly from RequestFilterAttribute.
public class RequiredAddressLinkedToAccount : AuthenticateAttribute
{
public RequiredRoleAttribute(ApplyTo applyTo)
{
this.ApplyTo = applyTo;
this.Priority = (int)RequestFilterPriority.RequiredRole;
}
public override void Execute(IRequest req, IResponse res, object requestDto)
{
var dto = requestDto as ILinkedToAccount;
var session = req.GetSession();
if(dto.AccountId == session.Id)
return; //we dont want anything to be blocked if the account Id is there.
//Implement like RequireRoleAttribute
if (DoHtmlRedirectIfConfigured(req, res))
return;
res.StatusCode = (int)HttpStatusCode.Forbidden;
res.StatusDescription = "Address does not belong to you";
res.EndRequest();
}
}
Related
What I want to achieve is to figure out where to initialize my sub-collections with aggregate root itself and validate business rules in a best practice way.
Here is my AppService:
public async Task<ReservationDto> CreateReservationAsync(CreateReservationInputDto input)
{
var reservation = await _reservationSystemManager.CreateAsync(
input.ReserverNotes
);
//should i send them directly to manager's createasync method but RequestedItems are dto objects.
//should i iterate through RequestedItems here and send them to manager one by one.
// where to throw business exception if RequestedItems count is 0.
}
Here is my inputdto:
public class CreateReservationInputDto
{
public string ReserverNotes { get; set; }
public Enum.Status Status { get; set; }
public List<CreateReservationItemInputDto> RequestedItems { get; set; }
}
Here is my aggregate root:
public class Reservation : FullAuditedAggregateRoot<Guid>
{
public Enum.Status Status { get; private set; }
public string ReserverNote { get; private set; }
public ICollection<ReservationItem> ReservationItems { get; set; }
public ICollection<OverduePayment> OverduePayments { get; set; }
private Reservation() { }
internal Reservation(
Guid id,
Enum.Status status,
[NotNull] string reserverNote,
) : base(id)
{
ReserverNote = reserverNote;
Status = status;
ReservationItems = new Collection<ReservationItem>();
OverduePayments = new Collection<OverduePayment>();
}
//I could not decide where and how to call this function from Domain Service.
internal void AddReservationItem(ReservationItem reservationItem)
{
if (ReservationItems.Any(r => r.Id == reservationItem.Id))
{
return;
}
ReservationItems.Add(reservationItem);
}
}
Well, depends on your business rules and your use cases. For example, if a reservation must have some reservation items, then I would create it in reservation constructor. Otherwise, if after creating reservation I can add new reservation items then I would be another use case and then AddReservationItem has sense for me.
Generally, if you need to inject more than one service (E.g. IUserRepository and IReservationItemsRepository) for validating your collection or any other property, you can create a domain service and implement your business logic and validate your collection with your needs.
If you don't need to inject any service to implement your business rules you can do it directly in your application service methods. In such cases, you can use data annotations for validating your properties in DTO classes as stated in here.
//should i send them directly to manager's createasync method but RequestedItems are dto objects.
//should i iterate through RequestedItems here and send them to manager one by one.
//where to throw business exception if RequestedItems count is 0.
In these three questions you've asked, should take it separately.
For instance, If you create a domain service class, it could be better to throw an exception if the RequestedItems count is 0 in that class' method. (And you can call, your AddReservationItem method from the domain service's method in that case.)
You can also check the best-practices documents of ABP.
I want to return a custom class from my custom AutoQuery endpoint that inherits QueryResponse<T> but adds a few extra properties.
public class WritingAssignmentBlogLookUpResponse : QueryResponse<BlogDto>, IResponse
{
public bool Success { get; set; }
public string Message { get; set; }
public string DebugMessage { get; set; }
}
But if I specify request like so:
[Route("/assignment/blogs/", "POST")]
public class WritingAssignmentBlogsLookUpRequest : QueryDb<Blog, BlogDto>, IReturn<WritingAssignmentBlogLookUpResponse>
{
}
Then the return type specified in generatd DTO for client.post(req) is QueryResponse<BlogDto> and it doesn't generate WritingAssignmentBlogLookUpResponse at all.
Do I just have to specify return type as any from my typescript service or is there a way to make the types match so I can strongly type it?
You can’t change AutoQuery responses which are already fixed in their service contract definition to return a QueryResponse<T>.
You can add extra info to the Meta Dictionary of the Response DTO (exists for this reason) otherwise if you need to change the Service Contract you’d need to convert it into a normal (I.e. non-AutoQuery) API which could use the Service Gateway to call an existing AutoQuery API that decorates the response.
I am currently working on a DDD-based application using Unity IOC container and need a way to pass my custom Principal object to the repository and service layers that would allow for unit testing. How should this be done? My current thoughts are to create a property on the service and repository classes of type IPrincipal. Then use Unity on Application_Start to set and pass in the Principal.
For one, am I on the right track in my thinking?
Two, if not at application_start, which seems like that is not the right place since I need a person to login first before the injections occur, where should this occur?
Three, for Unity, what should the container.RegisterType look like for getting the Principal from Thread.CurrentPrincipal or HttpContext.Current.User?
You can have a PrincipalDto class that will contain the relevant IPrincipal properties you need to use in your Service layer and map the values from the IPrincipal to the PrincipalDto. This way you do not need to include the reference assembly of IPrincipal to the other layers.
Below is an example that uses auto mapping.
public class PrincipalDto
{
public UserId { get; set; }
public Username { get; set; }
public RoleId { get; set; }
}
public class SomeService
{
public void SomeServiceMethod(PrincipalDto principal)
{
// do work here
}
}
public class SomeConsumer()
{
public void SomeConsumerMethod()
{
// where User is the IPrincipal object instance
var principal = Mapper.Map<PrincipalDto>(User);
var service = new Service();
service.SomeServiceMethod(principal);
}
}
I'm attempting to use the SimpleRepository to perform a fetch based on a non-ID property. Here's the Customer class I'm using:
[Serializable]
public class Customer : IEntity<Guid>
{
public Guid ProviderUserKey { get; set; }
public Guid ID
{
get; set;
}
}
I'm using SimpleRepository with migrations turned on. The code that throws the "Lambda Parameter not in scope" is below:
public class CustomerRepository :
ICustomerRepository
{
private readonly IRepository _impl;
public CustomerRepository(string connectionStringName)
{
_impl = new SimpleRepository(connectionStringName,
SimpleRepositoryOptions.RunMigrations);
}
public Customer GetCustomer(string userName)
{
var user = Membership.GetUser(userName);
// Code to guard against a missing user would go here
// This line throws the exception
var customer = _impl.Single<Customer>(c => c.ProviderUserKey.Equals(user.ProviderUserKey));
// Code to create a new customer based on the
// ASP.NET Membership user would go here
return customer;
}
}
I'm not sure at what point in the LINQ expression compilation this throws, but I am running this example on an empty database. The schema generations gets far enough to create the table structure, but can't evaluate the expression.
Does anyone know what I might be doing wrong?
Thanks!
I've had reports of this - can you add this (and your code) as an issue please?
We have a class Event (it's actually named differently, but I'm just making abstraction):
public class Event
{
public string Name { get; set; }
public string Description { get; set; }
public EventType EventType { get; set; }
}
We need to build an instance of a Message class with this object, but depending on the EventType, we use a different builder:
switch (event.EventType)
{
case EventType.First:
message = FirstMessageBuilder.Build(event);
break;
case EventType.Second:
message = SecondMessageBuilder.Build(event);
break;
}
Do you think this is acceptable, or should we take the following approach:
Make an abstract class:
public class Event
{
public string Name { get; set; }
public string Description { get; set; }
public abstract Message BuildMessage();
}
Then derive two classes: class FirstMessage and class SecondMessage and make the domain objects responsible for building the message.
I hope it isn't too abstract. The bottom line is we need to transform one class to another. A simple mapper won't do, because there are properties with XML content and such (due to a legacy application making the events). Just accept what we're trying to do here.
The real question is: can a domain object be responsible for such a transformation, or would you not recommend it? I would avoid the ugly switch statement, but add complexity somewhere else.
Whilst I agree with Thomas, you might want to look at the following design patterns to see if they help you:
Vistor Pattern
Double-Dispatch Pattern
Builder Pattern
Strictly speaking, a domain object shouldn't be responsible for anything other than representing the domain. "Changing type" is clearly a technical issue and should be done by some kind of service class, to maintain a clear separation of concerns...
In order to gain the readability of
var message = eventInstance.AsMessage();
as well following the single responsibility principle, you could define AsMessage() as an extension method of the event type.
There are few possible solutions. To use abstract factory:
public interface IMessageFactory
{
Message Create();
}
public class FirstMessageFactory : IMessageFactory
{
public Message Create()
{
//...
}
}
public class SomeService
{
private readonly IMessageFactory _factory;
public SomeService(IMessageFactory factory)
{
_factory = factory;
}
public void DoSomething()
{
var message = _factory.Create();
//...
}
}
Now you can wire IoC container to right factory for requested service.
To use Assembler which makes the transformation:
public interface IAssembler<TSource, TDestination>
{
TDestination Transform(TSource source);
}
This is quite similar to factory pattern, but if you are dependent on EventType, its possible to do it like:
public interface IAssembler<TEventType>
{
object Transform(object source);
}
I would encapsulate the logic into a separate Factory/Builder class, and use an extension method on Event to call the builder.
This would give you the best of both worlds.