ASP.NET MVC 3, RavenDB, & Autofac Issue Plus 2 Other Autofac Questions - asp.net-mvc-3

NOTE: There are 3 questions in here and I did not make separate questions since they are all somewhat related to the same code.
I have the following code that registers the connection to my RavenDB in the Application_Start once per the application's life cycle:
var store = new DocumentStore { Url = "http://localhost:8080" };
store.Initialize();
builder.RegisterInstance(store).SingleInstance();
Now this works fine and this is something that should be created only once per the application's life cycle. Now I wanted to add in the DocumentSession to Autofac so I tried to add in this in the Application_Start:
var session = store.OpenSession();
builder.RegisterInstance(session).SingleInstance();
In my UserRepository I have the following constructor:
public UserRepository(DocumentStore store, DocumentSession session)
When I try to run this, I get the follow runtime error:
Cannot resolve parameter 'Raven.Client.Document.DocumentSession Session' of constructor 'Void .ctor(Raven.Client.Document.DocumentStore, Raven.Client.Document.DocumentSession)'
That error to me sounds like Autofac does not think it has a DocumentSession however that is what store.OpenSession() returns so it should. Anyone know what would be causing this error? Am I not setting the session variable correctly (it is the same as the store variable which works fine)?
Another thing which may or may not be related to the above issue is how do I add an instance of an object to Autofac per request instead of per the applications life cycle? While the RavenDB DocumentStore object should only be created once be the life application cycle, the DocumentSession should be created once per the request (maybe creating it per application level is causing the error above).
One last question I will throw there about Autofac (mildly related to the code above) is about releasing the objects. If you take a look at this tutorial:
http://codeofrob.com/archive/2010/09/29/ravendb-image-gallery-project-iii-the-application-lifecycle.aspx
The last piece of code:
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
and the point of this code is to prevent leaking the sessions. Now is this something I also need to worry about for Autofac and if so, how would I do this in Autofac?

I'm guessing you want something like:
builder.Register(c => c.Resolve<DocumentStore>().OpenSession()).InstancePerLifetimeScope();
"The default ASP.NET and WCF integrations are set up so that InstancePerLifetimeScope() will attach a component to the current web request or service method call." - Autofac: InstanceScope
Basically, in a web app, InstancePerLifetimeScope handles the one per HTTP context aspect, and also disposes any types that implement IDisposable.

There was also the issue that OpenSession returns a IDocumentSession instead of a DocumentSession. Changing my class to look for a IDocumentSession along with doing what Jim suggested worked, thanks.

Related

Session object not available in WebAPI

I've got a webAPI that uses Entity Framework. I'm trying to cache some data in the session variable following along in this article:
https://msdn.microsoft.com/en-us/library/system.web.httpcontext.session(v=vs.110).aspx
I can't seem to do it though. The Session object isn't available.
In my controller, I try this:
Session["mappings"] = mappings;
...but it doesn't recognize what Session is.
I also try this:
HttpContext.Current.Session["mappings"] = mappings;
...and this:
Page.Session["mappings"] = mappings;
...but it doesn't know what HttpContext or Page are.
I'm including System.Web in my project references. I'm also including this in my web.config:
...just like this article says:
https://msdn.microsoft.com/en-us/library/ms178581(v=vs.110).aspx
...but to no avail.
My work colleague suggests it's because our webAPI is RESTful which means it's stateless, so no session object. However, we know there are ways around this. What I need is simply some way of persisting data in some kind of cache that will survive across several requests.
I also need something that will be available inside EF entities (not just the webAPI controller) is that's possible.
Does anyone know how to solve this problem? Thanks.
As your colleagues correctly suggested, an API is stateless, each request is separate and needs to have all the data required to complete the request.
You can add a caching layer however, but that is not going to be done via the Session object. Session makes no sense in an API.
Have a look here for some ideas: Caching Data in Web API

Dependency injected DbContext in a SignalR hub does not pull latest data

In my ASP.NET Core MVC site, I have a SignalR hub that has my DbContext injected into the constructor. The hub pulls data from the database and send it to a kendo ui grid for the user to view. This data is filtered in that hub on which group is selected (stored in the database).
The group selection is done outside the context of the hub. When I change the users selected group the page reloads to update various UI elements. When the signalr hub is then called, the selected group is still set as what it was prior to the change. After digging for a bit I came across this issue on the signalr github. What I understand is because the hub is transient, the DbContext is as well and since the hub is long running the DbContext is never updated.
Is there a simple way around this while still dependency injecting the DbContext or do I need to create and dispose a new context for every call? If so what is the best way to go about doing that and still pass the connection string from the appsettings.json?
EDIT
I am currently using Microsoft.AspNetCore.SignalR.Server and not the new Microsoft.AspNetCore.SignalR library.
The only way I could get around this issue with Microsoft.AspNetCore.SignalR.Server was to add a DbContextOptionsBuilder<T> singleton to the the ConfigureServices method in Startup.cs and then call that in a using(...) in the hub. While I feel this is a dirty way around the issue, I also believe it is the only way around the issue. Microsoft recently deprecated SignalR-Server and are moving to a new code base at SignalR. Hopefully this issue will be addressed in their new version.
Startup.cs
DbContextOptionsBuilder<PortalDbContext> builder = new DbContextOptionsBuilder<PortalDbContext>();
builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
services.AddSingleton(builder.Options);
Hub Classes
using (PortalDbContext dbContext = new PortalDbContext(_dbContextOptions))
{
...
}

How to stop grails erasing custom validation errors

In my Grails app, I am using methods in a service to do complicated validation for user submitted data. Unfortunately, Grails is quietly sabotaging me.
I populate the domain instance with the user submitted data
I hand the instance off to the service, which analyzes the properties.
If errors are found I add them using
instance.errors.rejectValue('myValue','errors.customErrorCode','Error')
BEHIND THE SCENES, when the service passes the domain instance back to the controller grails checks for changed properties and calls validate() before returning the instance. (verifiable by seeing the beforeValidate event called on returning a domain instance from a service to a controller where one or more properties has changed)
That behavior clears any custom errors I have added and the instance I get back in the controller is now incorrectly without error.
How can I
A) stop grails from validating between service and controller
OR
B) prevent a validate() call from wiping my custom errors.
EDIT
So far I've found one partial answer,
If you use instance.get(params.id), grails will self validate behind the scenes wiping custom errors.
If you use instance.read(params.id) you can bypass this behavior to an extent.docs
But this solution is limited by domain relationships. Any other solutions welcome.
Seems that it is not custom validation. It can be because of transactional service. Service opens separate transaction for each method and clears entities after method end. You can find this mentioned in docs(read the last paragraph of part ). So errors dessappear not because of validation.
Don't know if your service is transactional. But if it is - you can add #NotTransactional annotation to method were you want not to loose errors. And
errors will be saved.
Hope it helped,
Matvei.
Not sure how your code looks like or what is causing the problem, but in any case I strongly suggest implementing custom validators in the domain class or in a command object within the constrains.
Here are some examples from grails docs:
http://docs.grails.org/2.4.0/ref/Constraints/validator.html

StructureMap3 HybridHttpOrThreadLocalScoped with no HttpSessionState

I am trying to figure out how to setup a StructureMap3 configuration, that works in both a WebApi and in a Console application, like:
For<ISession>().HybridHttpOrThreadLocalScoped().Use(p => p.GetInstance<TestingContainer>().GetSession());
For console apps I would like the object to live as long as the thread lives, and for websites as long as the http-session lives.
This is possible with MVC websites because HybridHttpOrThreadLocalScoped use the HttpSessionState to determine whether to create a new instance or to reuse an existing instance.
WebApi doesn't have this HttpSessionState and therefore HybridHttpOrThreadLocalScoped won't work.
If I didn't care about the console app, then I would probably configure structuremap with Transient() or AlwaysUnique or similar.
So, what is the equivalent to HybridHttpOrThreadLocalScoped when there are no HttpSessionState instance.
Thank you.
EDIT
-to rearrange the question...
In general you should favor Nested Containers for lifecycle management. The reasons behind this are exactly what you've just noted, that in some situations using either Thread, HTTP, or hybrid scoped simply doesn't work. I've seen it cause huge issues before where people assume DB connections are being disposed because they are in other environments, but in one environment they aren't. Also, the explicitness is nice.
To do this set the dependencies you want disposed per request to Transient (the default) and dispose of the nested container at the end of the request. I've written about this workflow in webapi here. Additionally the official docs recommend this nuget.
For the console app you'll want to do something like this:
//parent Container set up at app start
public void On_UserAction()
{
//global container set up at app start, either use ObjectFactory (bad, deprecated and to be removed) or just keep track of it yourself.
using(var nestedContainer = GlobalContainer.GetNestedContainer())
{
var dependency = nestedContainer.GetInstance<DependencyThatHandlesUserInput>();
}
}
and that's it, the using block handles all the disposal for you.
If you have any other questions please ask, I've spent a lot of time on this sort of thing :).

"Default principal object cannot be set twice" error implementing WEB API with CSLA backend

Can anyone save some of my hair? :)
I'm trying to create an asp.net WEB API interface for an older CSLA (1.x/2.x era) project. I am testing by hard coding the login on every request in various ways (once in the startup code, as an authorization request filter, inside the individual route request etc etc). All the ways I tried work exactly once perfectly and then I get the infamous:
'Default principal object cannot be set twice.'
exception in BusinessPrincipal.vb (yeah I know it's very old, but it's released software, I can't upgrade CSLA)
I know that there is an issue where you need to set HttpContext.Current.User = Thread.CurrentPrincipal; due to some internal workings of the web API and I do that already, that has not resolved the issue.
I'd like to know if anyone has implemented a web api front end and how they handled this issue or any pointers as to what could be the solution.
Worst case scenario if I could at least just login once and keep that same principal without losing it I could implement a second layer of security, that woudld be acceptable, barring anything else is there some way to just login once and not lose that principal?
That BusinessPrincipal class would be in your code base, not in CSLA itself. The Csla.Security namespace does include a BusinessPrincipalBase that is probably the base class for your BusinessPrincipal.
Classes in that namespace are here in GitHub
It is true that you can only call AppDomain.SetPrincipalPolicy one time, but you should be able to set the Thread.CurrentPrincipal and HttpContext.Current.User multiple times.

Resources