ServiceStack: Adding routes dynamically - servicestack

I have not tried this yet, but I would like each module (Silverlight) to register its own routes, rather then adding it in application start.
Can routes be added to AppHost after application start, or do they all have to be immediatelly registered during Configure step?
I am thinking to scan all assemblies at the startup and provide AppHost with all assemblies that implement service stack services, but let each module add its own routes (have not figured out yet exact mechanism.
Before I go down this route, need to know if it is possible to add routes after the Configure step.

All configuration and registration in ServiceStack should be done within the AppHost.Configure() method and remain immutable thereafter.
If you want to encapsulate registrations of routes in a module than package it as a Plugin and register them manually on IPlugin.Register(IAppHost).
Here are some different ways to register routes:
public class MyModule : IPlugin
{
public void Register(IAppHost appHost)
{
appHost.Routes.Add<MyRequestDto>("/myservice", "POST PUT");
appHost.Routes.Add(typeof(MyRequestDto2), "/myservice2", "GET");
appHost.RegisterService(typeof(MyService), "/myservice3");
}
}
Then inside your AppHost.Configure you would register the Plugin, e.g:
Plugins.Add(new MyModule());

Related

ServiceStack register error form CustomUserAuth in CredentialsAuthProvider

searching the Internet I found many examples how to make your users table, everything works, check in on social networks, etc.
But I get problem when register's representative missions of RegistrationFeature.
It's a code and trace:
Thanks for help.
From v4.5.7+ that's now on MyGet you'll be able to use the built-in RegistrationFeature in ServiceStack with Custom IUserAuth and IUserAuthDetails data models.
For ServiceStack versions v4.5.6 and prior:
If you want to use Custom UserAuth tables you need to either inherit the existing UserAuth table, e.g:
public class LotoUserAuth : UserAuth {}
Which will let you use the existing Register Service.
Using a Custom Register Service
If you only want to implement IUserAuth you need to register a Custom Register Service that populates your Custom UserAuth table instead, which you can do by inheriting RegisterService<T> with your Custom UserAuth type, e.g:
public class CustomRegisterService : RegisterService<CustomUserAuth> { }
and register it in your AppHost with:
this.RegisterService<CustomRegisterService>("/register");
When using a Custom RegisterService you need to disable your existing configuration that registers the built-in RegisterService by removing these lines from your AppHost:
//authFeature.IncludeRegistrationService = true;
//Plugins.Add(new RegistrationFeature());
Finally since you're using a Custom RegisterService you'll need to register the RegistrationValidator which the RegistrationFeature would normally do in your AppHost with:
container.RegisterAs<RegistrationValidator, IValidator<Register>>();
AppHost Configuration Issues
Other problems with your AppHost is that you should register your Custom OrmLiteAuthRepository against the IAuthRepository interface:
container.Register<IAuthRepository>(c =>
new OrmLiteAuthRepository<LotoUserAuth, UserAuthDetails>(
c.Resolve<IDbConnectionFactory>()));
Then if you'll need to create the Schema with:
container.Resolve<IAuthRepository>().InitSchema();

Servicestack Multitenancy dynamic plugins

We are moving from an on premise-like application to a multi tenant cloud application.
for my web application we made a very simple interface based on IPlugin, to create a plugin architecture. (customers can have/install different plugins)
public interface IWebPlugin : IPlugin
{
string ContentBaseUrl { set; get; }
}
We have some plugins that would normally be loaded in on startup. Now i'm migrating the code to load at the beginning of a request (the Register function is called on request start), and scope everything inside this request.
It's not ideal but it would bring the least impact on the plugin system for now.
I could scope the Container by making an AppHost child container which would stick to the request:
Container IHasContainer.Container
{
get
{
if (HasStarted)
return ChildContainer;
return base.Container;
}
}
public Container ChildContainer
{
get { return HttpContext.Current.Items.GetOrAdd<Container>("ChildContainer", c => Container.CreateChildContainer()); }
}
problem case
Now im trying to make plugins work that actually add API services.
appHost.Routes.Add<GetTranslations>("/Localizations/translations", ApplyTo.Get);
But this service is unreachable (and not visible in metadata). How do i make it reachable?
I see you execute the following in ServiceController AfterInit. Re-executing this still wouldnt make it work.
//Copied from servicestack repo
public void AfterInit()
{
//Register any routes configured on Metadata.Routes
foreach (var restPath in appHost.RestPaths)
{
RegisterRestPath(restPath);
//Auto add Route Attributes so they're available in T.ToUrl() extension methods
restPath.RequestType
.AddAttributes(new RouteAttribute(restPath.Path, restPath.AllowedVerbs)
{
Priority = restPath.Priority,
Summary = restPath.Summary,
Notes = restPath.Notes,
});
}
//Sync the RestPaths collections
appHost.RestPaths.Clear();
appHost.RestPaths.AddRange(RestPathMap.Values.SelectMany(x => x));
appHost.Metadata.AfterInit();
}
solution directions
Is there a way i could override the route finding? like extending RestHandler.FindMatchingRestPath(httpMethod, pathInfo, out contentType);
Or could i restart the path compilation/caching? (would be enough for now that the service would be reachable tenant wide )
All configuration in ServiceStack should be contained within AppHost.Configure() and remain immutable thereafter. It's not ThreadSafe to modify ServiceStack's Static Configuration at runtime like trying to modify registered routes or Service Metadata which needs to be registered once at StartUp in AppHost.Configure().
It looks as though you'll need to re-architect your solution so all Routes are registered on Startup. If it helps Plugins can implement IPreInitPlugin and IPostInitPlugin interfaces to execute custom logic before and after Plugins are registered. They can also register a appHost.AfterInitCallbacks to register custom logic after ServiceStack's AppHost has been initialized.
Not sure if it's applicable but at runtime you can "hi-jack Requests" in ServiceStack by registering a RawHttpHandler or a PreRequestFilter, e.g:
appHost.RawHttpHandlers.Add(httpReq =>
MyShouldHandleThisRoute(httpReq.PathInfo)
? new CustomActionHandler((req, res) => {
//Handle Route
});
: null);
Simple answer seems to be, no. The framework wasn't build to be a run-time plugable system.
You will have to make this architecture yourself on top of ServiceStack.
Routing solution
To make it route to these run-time loaded services/routes it is needed to make your own implementation.
The ServiceStack.HttpHandlerFactory checks if a route exist (one that is registered on init). so here is where you will have to start extending. The method GetHandlerForPathInfo checks if it can find the (service)route and otherwise return a NotFoundHandler or StaticFileHandler.
My solution consists of the following code:
string contentType;
var restPath = RestHandler.FindMatchingRestPath(httpMethod, pathInfo, out contentType);
//Added part
if (restPath == null)
restPath = AppHost.Instance.FindPluginServiceForRoute(httpMethod, pathInfo);
//End added part
if (restPath != null)
return new RestHandler { RestPath = restPath, RequestName = restPath.RequestType.GetOperationName(), ResponseContentType = contentType };
technically speaking IAppHost.IServiceRoutes should be the one doing the routing. Probably in the future this will be extensible.
Resolving services
The second problem is resolving the services. After the route has been found and the right Message/Dto Type has been resolved. The IAppHost.ServiceController will attempt to find the right service and make it execute the message.
This class also has init functions which are called on startup to reflect all the services in servicestack. I didn't found a work around yet, but ill by working on it to make it possible in ServiceStack coming weeks.
Current version on nuget its not possible to make it work. I added some extensibility in servicestack to make it +- possible.
Ioc Solution out of the box
For ioc ServiceStack.Funq gives us a solution. Funq allows making child containers where you can register your ioc on. On resolve a child container will, if it can't resolve the interface, ask its parent to resolve it.
Container.CreateChildContainer()

Is there a way to remove the "/json/reply/" section of the url?

I would like the URL for a request to be /AmazingRequest (or even /AmazingService) instead of /json/reply/AmazingRequest.
I've tried the Route attribute, but it seems to have no effect. Is it possible within ServiceStack, or would I have to resort to URL rewriting?
This is what I've tried. It compiles, but the attribute has no effect.
public class MyServiceEndpoints : IService
{
[Route("/AmazingService")]
public AmazingResponse Post(AmazingRequest request)
{
return new Amazing(request).GetResponse();
}
}
I realize I would need to tell ServiceStack that it is a json request, but I'm fine with adding the Accept and Content-Type headers or maybe even a ?format=json to the query string.
P.S. I'm using the BSD version of ServiceStack
In ServiceStack Routes are defined on the Request DTO as it's part of your Service Contract, e.g:
[Route("/AmazingService")]
public class AmazingRequest { ... }
The pre-defined Route you're using is because ServiceStack doesn't think there's any custom route defined for your Service and just uses the default one.
The alternative way for declaring your Routes is to use the Fluent Registration API in your AppHost, e.g:
public void Configure(Container container)
{
Routes
.Add<AmazingRequest>("/AmazingService");
}
But the benefit of defining them on the Request DTO's is that your .NET Service Clients will also have access to them and will be able to use your custom routes instead of falling back to the pre-defined routes.

Configuring lifetime scopes in autofac when used as ServiceStack's IoC

I'm currently using AutoFac as the DI container for our ServiceStack web services app. I'm able to configure the wiring and everything, but after reading the section on Scopes, I'm at a loss at which scope would be best to use when registering my components. In our particular case, I think a PerHttpRequest scope would be OK since (please correct me if im wrong) I would want to dispose the dependencies as soon as the request ends.
My question is, how do I set this up in the container? I can't seem to find the "PerHttpRequest" lifetime scope within the included methods in autofac. I'm also unsure if ServiceStack does some kind of automagic to do this for me behind the scenes.
I'm using Autofac 3.0.1 on ServiceStack 3.9.35 on .Net 4 (running as a regular ASP host, not MVC). I'm also using the class described here as the IContainer adapter.
I wanted to avoid the overhead of the dependency on MVC, so the first answer didn't quite work for me.
Instead I used Funq to register a PerRequest ILifetimeScope, and resolve the ILifetimeScope in the ConatinerAdaptor before resolving the dependency.
public class AutofacLifetimeScopeIocAdapter : IContainerAdapter
{
private readonly Container _requestContainer;
public AutofacLifetimeScopeIocAdapter(Funq.Container requestContainer)
{
_requestContainer = requestContainer;
}
public T Resolve<T>()
{
var currentContainer = _requestContainer.Resolve<ILifetimeScope>();
return currentContainer.Resolve<T>();
}
public T TryResolve<T>()
{
var currentContainer = _requestContainer.Resolve<ILifetimeScope>();
T result;
if (currentContainer.TryResolve<T>(out result))
{
return result;
}
return default(T);
}
}
Then initialise with this
_autofacContainerRoot = builder.Build();
IContainerAdapter adapter = new AutofacLifetimeScopeIocAdapter(container);
container.Register<ILifetimeScope>((c) => _autofacContainerRoot.BeginLifetimeScope())
.ReusedWithin(ReuseScope.Request);
container.Adapter = adapter;
Then cleanup with
public override void OnEndRequest()
{
var currentContainer = _container.Resolve<ILifetimeScope>();
currentContainer.Dispose();
base.OnEndRequest();
}
This seems to behave as required for Autofac - SingleInstance, InstancePerDependency, and now InstancePerLifetimeScope which is perRequest.
Mythz response on the HostContext.Instance.Items collection can likely be used to remove the need for the
var currentContainer = _container.Resolve<ILifetimeScope>();
resolution, which should improve performance.
I think I have figured out how to make this work (using Autofac 2.6, which I am stuck on right now.) It involves using the following adapter and the Autofac.Mvc3 package:
public class AutofacIocAdapter : IContainerAdapter
{
private readonly IContainer _autofacRootContainer;
private readonly Container _funqContainer;
public AutofacIocAdapter(IContainer autofacRootContainer, Container funqContainer)
{
// Register a RequestLifetimeScopeProvider (from Autofac.Integration.Mvc) with Funq
var lifetimeScopeProvider = new RequestLifetimeScopeProvider(autofacRootContainer,null);
funqContainer.Register<ILifetimeScopeProvider>(x => lifetimeScopeProvider);
// Store the autofac application (root) container, and the funq container for later use
_autofacRootContainer = autofacRootContainer;
_funqContainer = funqContainer;
}
public T Resolve<T>()
{
return ActiveScope.Resolve<T>();
}
public T TryResolve<T>()
{
T result;
if (ActiveScope.TryResolve(out result))
{
return result;
}
return default(T);
}
private ILifetimeScope ActiveScope
{
get
{
// If there is an active HttpContext, retrieve the lifetime scope by resolving
// the ILifetimeScopeProvider from Funq. Otherwise, use the application (root) container.
return HttpContext.Current == null
? _autofacRootContainer
: _funqContainer.Resolve<ILifetimeScopeProvider>().GetLifetimeScope();
}
}
}
Steps to implement:
Add the Autofac.Mvc3 NuGet package to your web project (NOTE: does
not matter that your project isn't using MVC. The solution might be slightly different with Autofac 3, which cannot use Mvc3 integration.)
Follow the ServiceStack IoC page in hooking up a custom IContainerAdapter
for Autofac, using the following implementation
Note the RequestScope in ServiceStack's IOC only refers to ServiceStack's built-in Funq IOC.
To use RequestScope in another IOC Container like AutoFac you generally need to notify AutoFac at the end of the request so it can clean up all its request-scoped instances. To do this, ServiceStack provides the AppHostBase.OnEndRequest() hook you can override to get execute custom logic at the end of each request.
I'm not familiar with how AutoFac's custom lifetime scope works but more details about it can be found in:
AutoFac's InstanceScope wiki page
Primer on AutoFac's Lifetime scopes
Answer on how to manage AutoFac' request scope in MVC
Other info that might be useful for managing instances in ServiceStack is that every instance in put in the HostContext.Instance.Items dictionary or disposable added to HostContext.Instance.TrackDisposable are automatically disposed at the end of each request.
Update 2015-11-25: I changed the implementation by using global request and response filters. I put both ServiceStack V3 and V4 solutions into this repository and both versions are available as nuget packages.
I solved this problem by opening a new scope in Application_BeginRequest and disposing in Application_EndRequest. In the container adapter I check if this scope exists and use it, if not, I use the container. This allows using .InstancePerRequest() registration scope.
Described with gists here.

Pluggable service assemblies. How to add list of assemblies without hardcoding tem in the AppHost constructor

I have question about how to make service assemblies pluggable (read them from config file) into the ServiceStack.
I want to register my services assemblies from configuration file and not to hard code them in the AppHost constructor like this:
public appHost() : base("My Pluggable Web Services", typeof(ServiceAssembly1).Assembly, typeof(AnotherServiceAssembly).Assembly) { }
I couldn't find other way to register the assemblies outside of this constructor. The constructor also accepts params and does not have overload for example with IEnumerable<Assembly> as parameter.
The idea is to be able to plug service assemblies without touching the service stack REST web site.
I looked at the Plugin interface but I think it is more suitable to be used to extend the service stack not to dynamically plug service assemblies.
Are there any way to implement such pluggable service assemblies feature with the current service stack release? Can you also add constructor overload that will accept the array of assembly?
Thank you in advance
The purpose of your ServiceStack's AppHost is to be a bespoke class customized for your solution that has hard references to all your service dependencies. It's much easier to verify your application is configured correctly, at build time if you declare your dependencies in code as opposed to un-typed configuration.
Having said that you can override the strategy that ServiceStack uses to discover your Service types by overriding AppHostBase.CreateServiceManager():
protected virtual ServiceManager CreateServiceManager(params Assembly[] assembliesWithServices)
{
return new ServiceManager(assembliesWithServices);
//Alternative way to inject Container + Service Resolver strategy
//return new ServiceManager(new Container(),
// new ServiceController(() => assembliesWithServices.ToList().SelectMany(x => x.GetTypes())));
}
Otherwise you can still do what you want by just passing your assemblies into your AppHost, e.g:
var appHost = new AppHost("Service Name", MyConfig.LoadAssembliesFromConfig());
(new AppHost()).Init();

Resources