I've extended the CredentialsAuthProvider provided by service-stack to allow me to authenticate against a Active-Directory instance. The AD access logic is encapsulated within a custom class called AdManager (see below)
e.g.:
public class AdCredentialsAuthProvider : CredentialsAuthProvider
{
public override bool TryAuthenticate(IServiceBase authService,
string userName,
string password)
{
IAdManager manager = new AdManager();
return manager.Authenticate(userName, password);
}
...
Question:
I was hoping I could register the AdManager using service-stacks built-in IoC "Funq.Container" within my extended "AppHostBase" and access it from within my custom CredentialsAuthProvider? I tried registering it but have not found a way of accessing the IoC (or my registered AdManager object) via the service-stack built in framework.
Am I missing something?
Thanks
You can access the IOC from within the AuthProvider with the supplied IServiceBase, e.g:
var addManager = authService.TryResolve<IAdManager>();
Anywhere else you can always resolve dependencies using the Singleton:
var addManager = HostContext.TryResolve<IAdManager>();
Otherwise if you know it's in an ASP.NET Web Host you also access it via your AppHost singleton:
var addManager = AppHostBase.Instance.Resolve<IAdManager>();
Service Stack uses property injection as well. I have used property injection when extending the Service class provided by Service stack.
public class MyService : Service
{
public MyService(IDb db)
{
//db constructor inject
}
public IValidator<MyData> MyDataValidator { get; set; }
public object Get(MyData request)
{
//MyDataValidator is property injected
}
}
I believe the same logic can be applied to the AuthProvider. But I havent tested it.
Related
I am using Servicestack. I have a base class for my Services, like so:
public abstract class ServiceHandlerBase : Service
and then some methods and properties in there of interest. I already have several methods that accesses the IRequest object, like:
protected AlfaOnline GetContactItem()
{
string deviceUUID = Request.Headers.Get(Constants.DEVICE_UUID); // <-- calling this method from constructor will give NullRef on Request here
string authToken = Request.Headers.Get(Constants.AUTH_TOKEN);
// do stuff
return existingContactItem;
}
which works well inside my service implementations, no problems there.
Now, I wanted to use this exact same method directly from the base class, calling it in the constructor:
public ServiceHandlerBase()
{
AlfaOnline ao = GetContactItem();
}
but I then get a NullReferenceException on the Request object as noted above.
When is the Request object ready to access and use? Because it's not null inside the service implementations.
You can't access any dependencies like IRequest in the constructor before they've been injected, they're only accessible after the Service class has been initialized like when your Service method is called.
You can use a Custom Service Runner to execute custom logic before any Service is Executed, e.g:
public class MyServiceRunner<T> : ServiceRunner<T>
{
public override void OnBeforeExecute(IRequest req, TRequest requestDto) {
// Called just before any Action is executed
}
}
And register it with ServiceStack in your AppHost with:
public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext ctx)
{
return new MyServiceRunner<TRequest>(this, ctx);
}
But if you just want to run some logic for a Service class you can now override OnBeforeExecute() in your base class, e.g:
public abstract class ServiceHandlerBase : Service
{
public override void OnBeforeExecute(object requestDto)
{
AlfaOnline ao = GetContactItem();
}
}
See ServiceFilterTests.cs for a working example.
If you're implementing IService instead of inheriting the Service base class you can implement IServiceBeforeFilter instead.
The new Service Filters is available from v5.4.1 that's now available on MyGet.
I have inherited a stub project which is a HttpClient wrapper specific to an API enpoint we maintain.
The intention is to distribute this solution as nuget to other .NET teams that would need to consume the API endpoint.
Looking at the Autofac wire-up as a Module below - my question is would the consumer do this:
var client = PlayersAPIHttpClientModule("http:/api.players.com");
How does this setup facilitate the consumer to pass the base URI and then access the GetPlayerInformation method?
using Autofac;
using AutoMapper;
using Alpha.Domain.Players;
using System.Net.Http;
namespace Alpha.Clients.Players
{
public class PlayersAPIHttpClientModule : Module
{
private readonly string _serviceBaseUrl;
public PlayersAPIHttpClientModule(string serviceBaseUrl)
{
this._serviceBaseUrl = serviceBaseUrl;
}
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder.Register(ctx =>
{
var serviceClient = new HttpClient
{
BaseAddress =
new System.Uri(this._serviceBaseUrl)
};
return new
PlayerDomainManager(serviceClient,
ctx.Resolve<IMappingEngine>());
})
.SingleInstance()
.As<IPlayerDomainManager>();
}
}
}
This is the interface shared with the core domain.
public interface IPlayerDomainManager
{
IPlayer GetPlayerInformation (string playerId);
}
And this is the class itself with the exposed method functionality.
internal class PlayerDomainManager : IPlayerDomainManager
{
private readonly HttpClient _client;
private readonly IMappingEngine _mapper;
public PlayerDomainManager(HttpClient client, IMappingEngine mapper)
{
this._client = client;
this._mapper = mapper;
}
public IPlayer GetPlayerInformation(string playerId)
{
var response = this._client
.SendAsync
(new
HttpRequestMessage(HttpMethod.Get,
"/players/" + playerId),
CancellationToken.None)
.Result;
}
}
As described in the AutoFac Module documentation:
A module is a small class that can be used to bundle up a set of
related components behind a 'facade' to simplify configuration and
deployment. The module exposes a deliberate, restricted set of
configuration parameters that can vary independently of the components
used to implement the module.
As per the common use cases of Modules as described in the documentation, a common use case is to:
Configure related services that provide a subsystem, e.g. data access
with NHibernate
In the case of your code base, the PlayersAPIHttpClientModule is configuring the PlayerDomainManager as a service that implements the IPlayerDomainManager and configuring its lifetime to act as a singleton. The benefit is that the Module allows the deeply buried configuration requirement of the PlayerDomainManager (the base service url that in turn is required by one of its dependencies) to be surfaced as configuration centralised to the Modules constructor. This benefit would be more obvious if the configuration was more complex.
Modules need to be registered with AutoFac as per any other dependency:
builder.RegisterModule(new PlayersAPIHttpClientModule("base_service_url));
In turn, the services they configure are resolved using standard AutoFac dependency resolution.
scope.Resolve<IDomainPlayerManager>();
So, to answer your question, no you would not use the PlayersAPIHttpClientModule as per your question.
Register the PlayersAPIHttpClientModule with the AutoFac ContainerBuilder
Use the AutoFac Container to resolve the IDomainPlayerManager as required
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.
I have an IIS hosted app which takes an id from query string and instantiates user object like so. In AppHost.Configure I register UserService in IoC like so
container.Register(x => new UserService(x.Resolve<IDataContext>()).GetUser()).ReusedWithin(ReuseScope.Request);
My UserService (this is not a ServiceStack service, just an internal helper) looks like
public class UserService
{
public UserService(IDataContext dataContext)
{
_dataContext = dataContext;
}
public User GetUser()
{
var uid = HttpContext.Current.Request.QueryString["$id$"];
//snip
}
//snip
}
I want to change this to a self hosted app and therefore I don't have access to HttpContext any more. I have looked at HttpListenerContext but nothing seems to be populated when my class is being injected.
Can anyone shed any light on how to pass param from query string to this class?
You can't access any dependencies in your constructor and every ServiceStack action requires a Request DTO see the New API wiki for more details.
In your Service actions you can simply access the base.Request and base.Response when you need them e.g:
public class MyService : Service
{
public UserService UserService { get; set; }
public User Get(MyRequest request)
{
var user = UserService.GetUser(base.Request);
//snip
}
//snip
}
Note: there is no singleton for HttpListenerContext for Self-Hosting, so you can't get access to the runtime HTTP Request from inside an IOC lambda.
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) {}