Why does ServiceStack burden the DTOs with routing concerns? - servicestack

I'm learning ServiceStack, and from reading this page, a couple of things aren't clear to me.
So, considering this DTO pair:
[Route("/hello")]
[Route("/hello/{Name}")]
public class Hello : IReturn<HelloResponse>
{
public string Name { get; set; }
}
public class HelloResponse
{
public string Result { get; set; }
}
And this service:
public class MyService : Service
{
public object Any(Hello request)
{
return new HelloResponse { Result = $"Hello, {request.Name}!" };
}
}
Why is it the responsibility of Hello to specify the return-type using the marker interface IReturn<HelloResponse>?
It seems like this could be inferred from the return-type of MyService - except that it's conventional to use a return-type of object, which also requires type-casts in tests and client-code. Why?
And why are the Route attributes applied to the model Hello, rather than to the service MyService, where the request is actually handled?
It seems like both of these facts are more relevant to the service than to the model.
For one, a person reading the service declaration would more readily find the information pertaining to the service, instead of having to find it in the model.
For another, accepted HTTP methods are implicitly declared by the service via method-naming conventions - so it seems like the facts about service routing/dispatch are sort of scattered between two layers.
From that point of view, I was probably expecting something more along the lines of this:
// NON-VALID EXAMPLE
public class Hello
{
public string Name { get; set; }
}
public class HelloResponse
{
public string Result { get; set; }
}
public class MyService : Service
{
[Route("/hello")]
[Route("/hello/{Name}")]
public HelloResponse Any(Hello request)
{
return new HelloResponse { Result = $"Hello, {request.Name}!" };
}
}
What is the reason or the design thinking behind the conventions?
(Please don't take this as merely an attempt at critique - there's a lot of things I enjoy about this framework, and I am genuinely trying to understand the thinking behind these conventions.)

Why does ServiceStack burden the DTOs with routing concerns?
Note no routing concern burden is required at all in ServiceStack and all user-defined Routes are optional where all clients are able to call Services utilizing their automatic pre-defined routes.
Why is it the responsibility of Hello to specify the return-type using the marker interface IReturn?
It provides better typed access for client libraries like the generic C#/.NET Service Clients who are able to re-use the existing SericeModel DTOs to enable its optimal typed API without any code-gen, e.g:
var client = new JsonServiceClient(baseUrl);
var response = client.Get(new Hello { Name = "World" });
Or if you're not sharing DTOs it's also useful for Add ServiceStack Reference generated clients as well.
The return type on your Service implementation is meaningless in ServiceStack, i.e. has no behavioral difference, and would prevent the same Service implementation from returning the same Response DTO, or decorated with a custom HTTP Response, e.g:
public object Any(Hello request)
{
return new HelloResponse { Result = $"Hello, {request.Name}!" };
//...
return new HttpResult(new HelloResponse { Result = $"Hello, {request.Name}!" }) {
//... custom
};
}
both return types adhere to the API's IReturn<HelloResponse> contract
It's only useful for calling inter-process Services using the older ResolveService method, but for inter-prcess requests it's recommended to use the Service Gateway instead which also utilizes the type IReturn<T> interface markers for its Typed APIs.
The routes are not an implementation detail, they're apart of your public Service Contract and should be annotated on your DTOs which are used to define your Service Contract.
[Route("/hello")]
[Route("/hello/{Name}")]
public class Hello : IReturn<HelloResponse>
{
public string Name { get; set; }
}
public class HelloResponse
{
public string Result { get; set; }
}
Where they're used by the .NET ServiceStack Clients to send Service Client Requests.
var response = client.Get(new Hello { Name = "World" });
For another, accepted HTTP methods are implicitly declared by the service via method-naming conventions - so it seems like the facts about service routing/dispatch are sort of scattered between two layers.
Please see docs on Routing, the Route definition defines which methods the specific route is active on whilst the most appropriate Service implementation is invoked depending on the Request, e.g:
public object GetJson(Customers request) => ... // ONLY GET JSON Requests
public object Get(Customers request) => ... // All other GET Requests
public object Post(Customers request) => ... // ONLY POST Requests
public object Any(Customers request) => ... // ALL other Requests
What is the reason or the design thinking behind the conventions?
A lot of these issues is trying to blur the explicit typed Service Contract of your APIs and its concrete implementation, in ServiceStack these are distinct explicit concepts where all the information about your public Service Contract should be maintained in your implementation-free ServiceModel project.
Please read the Background Concepts docs to familiarize yourself with ServiceStack's purpose and goals.

Related

(ServiceStack) Location of business logic in a message based architecture

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();
}
}

Approach on mocking ServiceStack service being called by another ServiceStack service

Let's say we have a situation where a service would call other services in ServiceStack.
From reading around, this is how one would call another service:
public class CompanyService : Service
{
public SetupCompanyResponse Any(SetupCompany request)
{
var employeeService = base.ResolveService<EmployeeService>();
// Do something with employeeService
var response = employeeService.Any(new SetupEmployees());
return new SetupCompanyResponse { NumOfEmployeesCreated = response.Count };
}
}
Question: How do I mock EmployeeService if I'm unit-testing CompanyService?
Easiest way I could think of is to generate an IEmployeeService interface so that it's easily mockable. However I'm not sure if base.ResolveService<T> will be able to properly resolve and auto-wire a ServiceStack service, given its interface instead, like so:
var employeeService = base.ResolveService<IEmployeeService>();
Especially when we are registering services this way (which I assume is configuring the object resolution based on concrete class, and not the interface e.g IEmployeeService)
public HelloAppHost() : base("Hello Web Services", typeof(HelloService).Assembly) { }
Update:
Apparently I'm able to somewhat achieve this simply by:
1) Registering the service interface with its implementation
public static void SetupServices(Container container)
{
container.RegisterAs<EmployeeService, IEmployeeService>();
}
2) Using the same exact code to resolve, except now I pass in the interface. The service is successfully resolved.
var employeeService = base.ResolveService<IEmployeeService>();
3) All I need to do now is to override the resolver, and the service dependency should be totally mockable.
Question: Is this also a valid approach? Why or why not?
ServiceStack's Service class resolves all its dependencies from an IResolver, defined by:
public interface IResolver
{
T TryResolve<T>();
}
This can be injected in ServiceStack's Service class in an number of ways as seen by the implementation:
public class Service : IService, IServiceBase, IDisposable
{
public static IResolver GlobalResolver { get; set; }
private IResolver resolver;
public virtual IResolver GetResolver()
{
return resolver ?? GlobalResolver;
}
public virtual Service SetResolver(IResolver resolver)
{
this.resolver = resolver;
return this;
}
public virtual T TryResolve<T>()
{
return this.GetResolver() == null
? default(T)
: this.GetResolver().TryResolve<T>();
}
...
}
Which you can use to control how Services resolve dependencies.
An easy way to unit test Services is to use a BasicAppHost as seen on the Testing wiki, i.e:
appHost = new BasicAppHost().Init();
var container = appHost.Container;
container.Register<IDbConnectionFactory>(
new OrmLiteConnectionFactory(":memory:", SqliteDialect.Provider));
container.RegisterAutoWired<CompanyService>();
container.RegisterAutoWiredAs<StubEmployeeService, EmployeeService>();
Where StubEmployeeService is your stub implementation of EmployeeService, e.g:
public class StubEmployeeService : EmployeeService
{
public SetupEmployeesResponse Any(SetupEmployees request)
{
return new SetupEmployeesResponse { ... };
}
}
You can also register Services using any of the registration methods ServiceStack's IOC Supports if you prefer to use your own mocking library.

Service Stack IRequiresHttpRequest Pattern

How does this work? I've read the docs but am hoping for some more info.
From reading the docs I understand that when my DTO implements IRequiresHttpRequest, then the DTO's properties will not get automatically populated, but in my DTO I now have access to the HttpRequest object so I can change my DTO to have 'get' properties that pull things from the request object.
What is meant to inject the HttpRequest into my DTO? The docs suggest that service stack does this behind the scenes, however I can only get it to work if I register a custom request binder and manually inject the HttpRequest object.
RequestBinders.Add(typeof(MyDto), httpReq => {
var dto = new MyDto();
dto.HttpRequest = httpReq;
return dto;
});
Question 1: How exactly is the injection for IRequiresHttpRequest meant to work?
Question 2: Is there a way to gain access to the HttpRequest object so that my DTO can support custom 'get' properties, by still have service stack run it automatic mapping? For example:
public class MyDto
: IRequiresHttpRequest
{
public Int32 AutoMappedProperty1 { get; set; }
public Int32 AutoMappedProperty2 { get; set; }
public Int32 AutoMappedProperty3 { get; set; }
public Int32 AutoMappedProperty4 { get; set; }
public Int32 CustomMappedProperty { get { return customMappedProperty; } }
IHttpRequest httpRequest;
public IHttpRequest HttpRequest
{
get
{
return httpRequest;
}
set
{
httpRequest = value;
// lets say this searches the query string for a variety of
// different keys, and then maps one of them of
// CustomMappedProperty based upon a specific set of rules
customMappedProperty = [...]
}
}
}
In the case above I am defining how CustomMappedProperty gets populated, but I still want service stack to go ahead and map all of the 'set'-able properties. Is there a way to achieve this? Can I manually invoke the service stack dto mapper?
Which docs did you read about IRequiresHttpRequest? IRequiresHttpRequest works the same as IRequiresRequestContext which is only for decorating on Services and Validators to tell ServiceStack that it requires access and to inject the current IHttpRequest or IRequestContext.
The Custom Serialization / Deserialization wiki only mentions that IRequiresRequestStream and IRequiresSoapMessage can be used on Request DTOs to signal to ServiceStack to skip processing the Request body and allow you to manually deserialize the request yourself.

Add behavior to existing implementation - C# / Design Pattern

My current implementation for service and business layer is straight forward as below.
public class MyEntity { }
// Business layer
public interface IBusiness { IList<MyEntity> GetEntities(); }
public class MyBusinessOne : IBusiness
{
public IList<MyEntity> GetEntities()
{
return new List<MyEntity>();
}
}
//factory
public static class Factory
{
public static T Create<T>() where T : class
{
return new MyBusinessOne() as T; // returns instance based on T
}
}
//Service layer
public class MyService
{
public IList<MyEntity> GetEntities()
{
return Factory.Create<IBusiness>().GetEntities();
}
}
We needed some changes in current implementation. Reason being data grew over the time and service & client cannot handle the volume of data. we needed to implement pagination to the current service. We also expect some more features (like return fault when data is more that threshold, apply filters etc), so the design needs to be updated.
Following is my new proposal.
public interface IBusiness
{
IList<MyEntity> GetEntities();
}
public interface IBehavior
{
IEnumerable<T> Apply<T>(IEnumerable<T> data);
}
public abstract class MyBusiness
{
protected List<IBehavior> Behaviors = new List<IBehavior>();
public void AddBehavior(IBehavior behavior)
{
Behaviors.Add(behavior);
}
}
public class PaginationBehavior : IBehavior
{
public int PageSize = 10;
public int PageNumber = 2;
public IEnumerable<T> Apply<T>(IEnumerable<T> data)
{
//apply behavior here
return data
.Skip(PageNumber * PageSize)
.Take(PageSize);
}
}
public class MyEntity { }
public class MyBusinessOne : MyBusiness, IBusiness
{
public IList<MyEntity> GetEntities()
{
IEnumerable<MyEntity> result = new List<MyEntity>();
this.Behaviors.ForEach(rs =>
{
result = rs.Apply<MyEntity>(result);
});
return result.ToList();
}
}
public static class Factory
{
public static T Create<T>(List<IBehavior> behaviors) where T : class
{
// returns instance based on T
var instance = new MyBusinessOne();
behaviors.ForEach(rs => instance.AddBehavior(rs));
return instance as T;
}
}
public class MyService
{
public IList<MyEntity> GetEntities(int currentPage)
{
List<IBehavior> behaviors = new List<IBehavior>() {
new PaginationBehavior() { PageNumber = currentPage, }
};
return Factory.Create<IBusiness>(behaviors).GetEntities();
}
}
Experts please suggest me if my implementation is correct or I am over killing it. If it correct what design pattern it is - Decorator or Visitor.
Also my service returns JSON string. How can I use this behavior collections to serialize only selected properties rather than entire entity. List of properties comes from user as request. (Kind of column picker)
Looks like I don't have enough points to comment on your question. So, I am gonna make some assumption as I am not a C# expert.
Assumption 1: Looks like you are getting the data first and then applying the pagination using behavior object. If so, this is a wrong approach. Lets say there are 500 records and you are showing 50 records per fetch. Instead of simply fetching 50 records from DB, you are fetching 500 records for 10 times and on top of it you are adding a costly filter. DB is better equipped to do this job that C# or Java.
I would not consider pagination as a behavior with respect to the service. Its the behavior of the presentation layer. Your service should only worry about 'Data Granularity'. Looks like one of your customer wants all the data in one go and others might want a subset of that data.
Option 1: In DAO layer, have two methods: one for pagination and other for regular fetch. Based on the incoming params decide which method to call.
Option 2: Create two methods at service level. One for a small subset of data and the other for the whole set of data. Since you said JSON, this should be Restful service. Then based on the incoming URL, properly call the correct method. If you use Jersey, this should be easy.
In a service, new behaviors can be added by simply exposing new methods or adding new params to existing methods/functionalities (just make sure those changes are backward compatible). We really don't need Decorator or Visitor pattern. The only concern is no existing user should be affected.

ServiceStack - Empty Request Classes?

I have a question regarding ServiceStack. Why are there empty Request Classes, why do we have to have a Request Class? For example:
[Route("/test", "GET")]
public class Test
{
}
public class TestResponse
{
public string Date { get; set; }
}
public class TestService : Service
{
public object Get(Test test)
{
return new TestResponse { Date = DateTime.Now.ToString() };
}
}
If I don't pass an object with my request, my service fails?
Then I'm my Global.asax file, I have:
public class AxDataAppHost : AppHostBase
{
public AxDataAppHost() :
base("AxData", typeof(TestService).Assembly)
{
}
}
What if I have more than 1 service, in the example above I'm using TestService but what if I have one for Customers, Orders and Products? How do I handle multiple services?
why do we have to have a Request Class?
ServiceStack is a message-based framework that embraces Martin Fowler's Remote Service Best Practices (i.e. Remote Facade, DTOs and Gateway) which utilizes a ServiceGateway to send coarse-grained Request DTOs which commonly returns a typed Response DTO (though services can return anything). Using a message-based design has many advantages and is what enables ServiceStack's typed end-to-end API.
E.g. you can re-use these types you defined your services with:
public class Test : IReturn<TestResponse> {}
public class TestResponse
{
public string Date { get; set; }
}
On the client, which is what gives you a typed API without code-gen, e.g:
var client = new JsonServiceClient(BaseUri);
TestResponse response = client.Get(new Test());
Note: you don't even need custom routes as by default ServiceStack's C# clients will fallback to use the pre-defined routes (enabled by default).
What if I have more than 1 service, in the example above I'm using TestService but what if I have one for Customers, Orders and Products? How do I handle multiple services?
In your AppHost base constructor you're passing in an assembly (i.e. NOT a single service):
public AxDataAppHost() : base("AxData", typeof(TestService).Assembly) {}
This tells ServiceStack where to look for and wire-up all your services. You only need to do this once for each dll/assembly that your services are in.
ServiceStack's AppHosts also allows specifying multiple assemblies which you can use to wire-up services located in multiple assemblies, e.g:
public AxDataAppHost()
: base("AxData", typeof(TestService).Assembly, typeof(ServiceInNewDll).Assembly) {}

Resources