Dependency injection of IAuthSession resolves empty session - servicestack

I am successfully using ServiceStack's credentials authentication along with a custom AuthUserSession. What I can't work out is how to use this in classes that have had dependencies injected via Funq.
I have several "Business" Classes which rely on Funq to inject the DAL dependency into them, this works perfectly.
However, within the DAL I obviously want to mark database fields such as "CreatedBy" and "ModifiedBy" with the currently logged in user id. So, I create a constructor parameter in the DAL to receive the AuthUserSession.
Within Global.asax, the following lines are in place:
//authentication
Plugins.Add(new AuthFeature(() => new MyAuthUserSession(),
new IAuthProvider[] { new MyCredentialsAuthProvider() }));
No matter how I register MyAuthUserSession with funq, it resolves to an instance with no Session information in it.
container.Register<IAuthSession>(new MyAuthUserSession());
or
container.Register(new MyAuthUserSession());
In a nutshell; What is the best way of getting "Current User ID" into a class via constructor injection?

UserSessions are not dependencies that are resolved from an IOC and as such should never be registered in an IOC which would be meaningless and cause confusion on how they actually work.
They are models that are hydrated from a Cache at runtime using the client's Cookies that are passed in with each HTTP Request. The Session wiki has more information about how Sessions work in ServiceStack.
Custom Typed User Sessions can be resolved in ServiceStack using the base.SessionAs<T> method, e.g:
public class MyService : Service
{
public MyDependencyThatUsesUserSession MyDep { get; set; }
public object Any(Request request)
{
MyAuthUserSession mySession = base.SessionAs<MyAuthUserSession>();
return MyDep.Execute(mySession, request.Id);
}
}

Related

ServiceStack: Generate OpenAPI spec without creating the Service implementation classes

ServiceStack has support for OpenAPI and can generate an OpenAPI spec. However, for APIs/endpoints to be generated in the spec, it is not enough to specify the API details using the Route attributes as described here, you also need to create the Service classes that (eventually) implement the functionality.
Is there a way to make the OpenAPI specification include everything without having to create the Service classes that go with them?
The reason is that sometimes you just want to work on the specification, not implementation (even though you can just skip implementation details and throw a NotImplementedException), and creating those Service classes just to get the spec to show is annoying.
If it doesn't have an implementation it's not a Service and therefore wont have any of ServiceStack's metadata or features available for it.
If you want to skip their implementation you can just create stub implementations for them, e.g:
public class MyServices : Service
{
public object Any(MyRequest1 request) => null;
public object Any(MyRequest2 request) => null;
public object Any(MyRequest3 request) => null;
}

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

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.

How to get subdomain in UserProvider

Im doing multitenant service where im validate users against:
username, password, subdomain
Me using FOSUserBundle
I would like to use UserProvider to be aware of from wchich domain its called and then make user find.
Problem is i can't get access to #request whatever i try container or set injections i got
"ScopeWideningInjectionException: Scope Widening Injection detected"
is there any proper way to extend FOSUserBundle to be request aware when validate (make user login) username ?
Have you tried "Changing the scope of UserProvider? http://symfony.com/doc/current/cookbook/service_container/scopes.html
my_user_provider:
class: Acme\HelloBundle\UserProvider
scope: request
arguments: [#request]
Not sure if it will work in this case. The security stuff it tricky.
An alternative might be to create a REQUEST listener, have it pull the subdomain and then have it inject it into the user provider.
I had the same issue, with Symfony 2.1 I was able to give the #service_container as parameter directly in my provider and then getting the request...
Since I updated to SF 2.2, not working anymore !
Even if you set "scope: active", or "public: true" in your configuration.
If you try to get the request by an intermediate listener, it doesn't work too... It seems since SF2.2 that the request is not injected in time or something like that.
So here how I can get the request inside the provider, I don't know if it's clean but this is the only solution I found, I pasted the 2 solutions, for sf 2.2 and sf 2.1 :
SF 2.2
Provider class :
use Symfony\Component\HttpFoundation\Request;
// ...
class WebsiteUserProvider implements UserProviderInterface
{
private $websiteUrl;
// ...
public function __construct(UserManager $userManager)
{
$this->userManager = $userManager;
// Works for sf2.2, init manually the request
$request = Request::createFromGlobals();
$this->websiteUrl = $request->getHost();
}
// ...
}
That's it !
SF 2.1
Provider class :
// ...
class WebsiteUserProvider implements UserProviderInterface
{
private $websiteUrl;
// ...
public function __construct($container, UserManager $userManager)
{
$this->userManager = $userManager;
if ($container->isScopeActive('request')) {
$this->websiteUrl = $container->get('request')->getHost();
}
}
// ...
}
Configuration :
sybio_website.user_provider:
class: Sybio\Bundle\WebsiteBundle\Security\Authentication\Provider\WebsiteUserProvider
arguments: [#service_container, #sybio.user_manager]
Finaly I did it this way:
Used SyndMultiTenantBundle for multitenant propose with domainstrategy
and to make it work with FOSUserBundle:
Create new UserManager & UserRepository classes
Override your UserManager:loadUserByUsername method to query your repository directly
Compiler pass to use your custom use manager (change
class of definition)
Add a listener on tenant.found to call
$userManager->setTenant($event->getTenant()) to pass tenant into
scope of repository
Thanks to Adrian from SyndicateTheory
It works like a charm - Enjoy!

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.

Resources