WCF app . Structure map Objectfactory losing instance of an Object - wcf

I am trying to get WCF work with Structuremap. I took most of the code from Jimmy Bogard's blog
Integrating StructureMap with WCF
I am reusing all my objects (Domain, NHIBERNATE , Service layer ) that was created for ASP.nET MVC application.I have a separate IoC Library where I bootstrap all regisrties
I have added global.asax and in Application Start Event this is what I have :
var webServiceRegistry = new WebServiceRegistry();
var bootStrapper = new IoC.BootStrapper();
bootStrapper.Start();
WebServiceRegistry is a normal class and in its constructor I have the following:
var appUser = new AppUser
{
Role = userDto.Role,
Email = userDto.Email,
Id = userDto.Id,
CompanyName = dealerDto.Name,
Name = userDto.Name,
IsImpersonated = false,
Impersonater = Guid.Empty
};
System.Threading.Thread.CurrentPrincipal = System.Web.HttpContext.Current.User = appUser;
ObjectFactory.Configure(x => x.For<IAppUser>().Use(appUser));
Everything goes fine - no errors
Things start to fail when my my wcf service class is being instantiated which has a Domainservice object (IDomainServiceObject domainServiceObject) in constructor with 202 error.
The failure is in DomainService Registry where it fails to get default instance of IAppUser
Edit
Initial problem was in that I had error in constructor of StructureMapServiceHost.
Now I dont get any error but I am not getting the instance of IAppUser that I inject. In place of that it creates a new instance of AppUser.
Do anyone have a clue as to why this happens?
I have tried adding HttpContextScope , HybridHttpOrThreadLocalScoped and still same result
I have conformed that at the time all registries are called in bootstrapper IAppUser instance is the once that was provided with values in it (and not created by StructureMap)
In Application Start it does create the whole graph .
As soon as it enters webmethod ILMSUser is a new instance.
Thank you

Since you want the same object back every time you can use singleton
this.For<IAppUser>().Singleton().Use(appUser);

Related

How to inject the .NET Core [IServiceProvider] itself into services?

How to inject the [IServiceProvider] interface into custom services? I mean after the [Startup] class finishes construction of [IServiceProvider] from [IServiceCollection] set of bindings. How do I then subscribe to the newly created [IServiceProvider] built after method [ConfigureServices] invoked?
If you want to call your service inside startup you should create a scope
// initial database
using (var scope = app.ApplicationServices.CreateScope())
{
var initDatabase = new YourClass(scope.ServiceProvider.GetService<YourServiceInterface>());
}
But Accessing to IServiceProvider in other services don't make sense. If you describe more You could get the right answer.

User.Identity.Name throw Object reference not set to an instance

I have this code
public UserProfile spUserProfileGet()
{
// this line throw : Object reference not set to an instance
var user = HttpContext.Current.User.Identity.Name;
//...
}
In my IIS Development setting, I have
Anonymous Authentication : Disabled
Windows Authentication : Enabled
And i am getting
Object reference not set to an instance
Why is that ? I am using this class in many projects before with no problem :/
The HttpContext.Current.User is NULL, but why ?
The problem was, that I called HttpContext.Current.User from global.asax Application_BeginRequest() which does not contain this object yet. Here is description of application lifecycle https://msdn.microsoft.com/en-us/library/ms178473.aspx and when I copy the code to the
Application_PostAuthenticateRequest, It works now.
The problem that remains, is that Application_PostAuthenticateRequest is triggered twice.

ServiceStack: Can we Pass Data through a RequestFilterAttribute to the calling service

Maybe I'm thinking about this wrong, but I'm trying to create a custom attribute for our CMS to handle auth checks.
https://gist.github.com/sitefinitysteve/62ab761256a64a84d8a6#file-sitefinityjwt-cs-L39
So if this service is called from within the CMS from a logged in user, user data is all there for the service method already.
But in the context of being called from an app, the user is technically Anonymous, however I can decode the token and get the user just fine... but not sure how to like pass that over to the service.
Am I just maybe looking at this wrong, and the proper thing to do is to call a CMS API method to just log that person in (seems slow if I already have the persons user object from line 33, and the service context expires instantly.
Use Request.Items Dictionary
You would use the IRequest.Items dictionary for any data you want to pass throughout ServiceStack's Request Pipeline:
//RequestFilter:
req.Items["info"] = new MyRequestInfo { ... };
In Service:
var info = (MyRequestInfo)base.Request.Items["info"];
Have DTO's share common interface
Another option for adding extra info to your Service is to have Request DTO's implement an interfaces, e.g:
public interface IHasInfo
{
MyRequestInfo Info { get; set; }
}
Which you could then populate in your Request Filter, e.g:
((MyRequestInfo)dto).Info = new MyRequestInfo { ... };
Access in Service like any other DTO property, e.g:
public object Any(Request request)
{
var info = request.Info;
}

Ninject Inject Common DbContext Into Numerous Repositories

There’s something which I am doing that is working, but I think it can probably be done a lot better (and therefore, with more maintainability).
I am using Ninject to inject various things into a controller. The problem which I needed to solve is that the DbContext for each repository needed to be the same. That is, the same object in memory.
Whilst, the following code does achieve that, my Ninject common config file has started to get quite messy as I have to write similar code for each controller:
kernel.Bind<OrderController>().ToMethod(ctx =>
{
var sharedContext = ctx.Kernel.Get<TTSWebinarsContext>();
var userAccountService = kernel.Get<UserAccountService>();
ILogger logger = new Log4NetLogger(typeof(Nml.OrderController));
ILogger loggerForOrderManagementService = new Log4NetLogger(typeof(OrderManagementService));
var orderManagementService = new OrderManagementService(
new AffiliateRepository(sharedContext),
new RegTypeRepository(sharedContext),
new OrderRepository(sharedContext),
new RefDataRepository(),
new WebUserRepository(sharedContext),
new WebinarRepository(sharedContext),
loggerForOrderManagementService,
ttsConfig
);
var membershipService = new MembershipService(
new InstitutionRepository(sharedContext),
new RefDataRepository(),
new SamAuthenticationService(userAccountService),
userAccountService,
new WebUserRepository(sharedContext)
);
return new OrderController(membershipService, orderManagementService, kernel.Get<IStateService>(), logger);
}).InRequestScope();
Is there a neater way of doing this?
Edit
Tried the following code. As soon as I make a second request, an exception is chucked that the DbContext has already been disposed.
kernel.Bind<TTSWebinarsContext>().ToSelf().InRequestScope();
string baseUrl = HttpRuntime.AppDomainAppPath;
kernel.Bind<IStateService>().To<StateService>().InRequestScope();
kernel.Bind<IRefDataRepository>().To<RefDataRepository>().InRequestScope().WithConstructorArgument("context", kernel.Get<TTSWebinarsContext>());
var config = MembershipRebootConfig.Create(baseUrl, kernel.Get<IStateService>(), kernel.Get<IRefDataRepository>());
var ttsConfig = TtsConfig.Create(baseUrl);
kernel.Bind<MembershipRebootConfiguration>().ToConstant(config);
kernel.Bind<TtsConfiguration>().ToConstant(ttsConfig);
kernel.Bind<IAffiliateRepository>().To<AffiliateRepository>().InRequestScope().WithConstructorArgument("context", kernel.Get<TTSWebinarsContext>());
kernel.Bind<IWebinarRepository>().To<WebinarRepository>().InRequestScope().WithConstructorArgument("context", kernel.Get<TTSWebinarsContext>());
kernel.Bind<IWebUserRepository>().To<WebUserRepository>().InRequestScope().WithConstructorArgument("context", kernel.Get<TTSWebinarsContext>());
kernel.Bind<IOrderRepository>().To<OrderRepository>().InRequestScope().WithConstructorArgument("context", kernel.Get<TTSWebinarsContext>());
kernel.Bind<IInstitutionRepository>().To<InstitutionRepository>().WithConstructorArgument("context", kernel.Get<TTSWebinarsContext>());
kernel.Bind<IUserAccountRepository>().To<DefaultUserAccountRepository>().InRequestScope();
kernel.Bind<IRegTypeRepository>().To<RegTypeRepository>().InRequestScope().WithConstructorArgument("context", kernel.Get<TTSWebinarsContext>());
kernel.Bind<UserAccountService>().ToMethod(ctx =>
{
var userAccountService = new UserAccountService(config, ctx.Kernel.Get<IUserAccountRepository>());
return userAccountService;
});
kernel.Bind<IOrderManagementService>().To<OrderManagementService>().InRequestScope();
//RegisterControllers(kernel, ttsConfig);
kernel.Bind<AuthenticationService>().To<SamAuthenticationService>().InRequestScope();
kernel.Bind<IMembershipService>().To<MembershipService>().InRequestScope();
There's something about InRequestScope I'm misunderstanding.
Edit:
.InRequestScope() will ensure everything which gets injected that binding will receive exactly the same instance when during injection (creation) the HttpContext.Current is the same. That means when a client makes a request and the kernel is asked to provide instances with .InRequestScope(), it will return the same instance for the exact same request. Now when a client makes another request, another unique instance will be created.
When the request ends, ninject will dispose the instance in case it implements IDisposable.
However consider the following scenario:
public class A
{
private readonly DbContext dbContext;
public A(DbContext dbContext)
{
this.dbContext = dbContext;
}
}
and binding:
IBindingRoot.Bind<DbContext>().ToSelf().InRequestScope();
IBindingRoot.Bind<A>().ToSelf().InSingletonScope();
You got yourself a major problem. There's two scenarios how this can pan out:
You are trying to create an A outside of a request. It will fail. Instantiating the DbContext, ninject will look for HttpContext.Current - which is null at the time - and throw an Exception.
You are trying to create an A during a request. Instantiating will succeed. However, When you try to use some functionality of A (which is accessing DbContext in turn) after the request or during a new request, it will throw an ObjectDisposedException
To sum it up, an ObjectDisposedException when you access the DbContext can only be caused by two scenarios:
-you ar disposing the DbContext (or some component which in turn disposes the DbContext) before the request is over.
-you are keeping a reference to the DbContext (again, or to some component which in turn references the DbContext) across request boundaries.
That's it. Nothing complicated about this, but your object graph.
So what would help is drawing an object graph. Start from the root / request root. Then when you're done, start from the DbContext and check who's calling Dispose() on it. If there is no usage inside your code, it must be Ninject who's cleaning up when the request ends. That means, you need to check all references to the DbContext. Someone is keeping a reference across requests.
Original Answer:
You should look into scopes: https://github.com/ninject/ninject/wiki/Object-Scopes
Specifically, .InRequestScope() - or in case that is not appliccable to your problem - .InCallScope() should be interesting to you.
As you are already using .InRequestScope() for the original binding, i suggest that binding the shared context type also .InRequestScope() should be sufficient. It means every dependency of the OrderController will receive the same webinar context instance. Furthermore, if someone else in the same request wants to get a webinar context injected, he will also get the same instance.
You should look into scopes: https://github.com/ninject/ninject/wiki/Object-Scopes
Specifically, .InRequestScope() - or in case that is not appliccable to your problem - .InCallScope() should be interesting to you.
As you are already using .InRequestScope() for the original binding, i suggest that binding the shared context type also .InRequestScope() should be sufficient. It means every dependency of the OrderController will receive the same webinar context instance. Furthermore, if someone else in the same request wants to get a webinar context injected, he will also get the same instance.

gSOAP instance of .NET service

I have a linux c++ client (via gSOAP) to WCF c# server. The WCF c# service contains list of objects, on which some action is executed. Each time i call some function on service, the new object is created, action on that object is executed and that object lands into list in service. at the end i am calling another function on service, which loops over all objects in a list and executes another call on them. this works as intended on c#, with both client and service pure WCF.
it works different via gSOAP. each time i call a first function on service via gSOAP, that action is executed and list is updated. but it is each time new service. so basically i am dealing each time with new service. i do not wont serialize/deserialize object itself, to have it on inux side.
any ideas how to solve this?
on c# side i have something like (unnecessery details skipped)
class Service : IService
{
List list = new List();
void func1(int i)
{
Class1 c = new Class1(i);
c.create();
list.Add(c);
}
void func2()
{
foreach(Class1 c in list)
{
c.close();
}
}
}
on gSOAP side i have something like
Proxy service (endpoint);
service.func1(1);
service.func1(2);
//...
service.func2();
as i said problem is: when func2() is executed it operates on empty list, meaning gSOAP object of Proxy service does not contain c# object of service.
Help, help!
ps.
the solution is found: container made "static" does the trick.