Issues saving session objects using simple-injector - asp.net-mvc

I have MVC application where I am trying to save some objects in session using DI framework of simple injector.
I register the objects as below
container.RegisterPerWebRequest<Func<HttpSessionState>>(() =>
() => HttpContext.Current.Session);
container.RegisterSingle<MemoryCache>(() => MemoryCache.Default);
container.RegisterPerWebRequest<ISessionCacheService, SessionCacheService>();
Now in the session service constructor I am able to see the multi-cast delegate for sessionstate object but when I try to add other objects I get the Object reference error. The constructor is listed below
protected internal Func<HttpSessionState> _HttpSessionState;
public SessionCacheService(Func<HttpSessionState> httpSessionState)
{
_HttpSessionState = httpSessionState;
}
I get the error in the following line of code inside a method of this service
public void Set<T>(string key, T data)
{
_HttpSessionState()[key] = data;
}
Here I can see that the following variable is null
this._HttpSessionState()
The main reason why we need to use this construct is that we need to store multicast delegate to session as shown in the example below
public RuntimeContext Current
{
get
{
Func<RuntimeContext> getRuntimeContextFunc = () =>
{
return new RuntimeContext()
{
ImpersonatingAgentId = Guid.Empty
};
};
return this._SessionCacheService.Get<RuntimeContext>(
typeof(RuntimeContext).ToString(),
getRuntimeContextFunc);
}
}
Later on we can retrieve these items from session using the get method
public T Get<T>(string key, Func<T> acquire)
{
if (this.IsSet(key))
{
return this.Get<T>(key);
}
else
{
var result = acquire();
this.Set<T>(key, result);
return result;
}
}

Related

MVC simple insert not updating database

The is driving me nuts. Im trying to do a "simple" record insert and I can only get it to work if I store the context in a variable or create a local context. I tried to keep the context and model object tied together but no luck so far.
public class TransactionDataAccessLayer
{
public cartableContext transactionContext
{
get
{
return new cartableContext();
}
}
}
class TransactionBusinessLayer
{
Cardata newCar = new Cardata();
public void addCar(Cardata cd)
{
try
{
//this works. Storing the context in ctc2 seems to make it work???
TransactionDataAccessLayer tdal = new TransactionDataAccessLayer();
cartableContext ctc2 = tdal.transactionContext;
ctc2.cardata.Add(cd);
ctc2.SaveChanges();
//this does not work
tdal.transactionContext.cardata.Add(cd);
tdal.transactionContext.Entry(cd).State = EntityState.Modified;
tdal.transactionContext.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
}
}
}
In C#, properties are basically just fancy methods, designed to make it easier to access private fields. Therefore, returning a new Context in your getter will do just that; return a new one each time it is accessed. To preserve state, you need to contain your context in a private field, like so:
public class TransactionDataAccessLayer
{
private cartableContext _transactionContext;
public cartableContext transactionContext
{
get
{
if (_transactionContext == null)
_transactionContext = new cartableContext();
return _transactionContext;
}
}
}

Is it possible to prevent Delegate Factory creation in Autofac?

I am updating a library that uses Autofac so that, in addition to the original configuration file (registered via Autofac), it can optionally take a function to accomplish that same goal (again, registered via Autofac). The original is something like this:
public MyClass(ConfigFile config = null)
{
this._activatorLoader = a => {
// old config code here...
}
}
The updated version I'd like is:
public MyClass(
Func<Input, IList<Activator>> activatorLoader = null,
ConfigFile config = null)
{
if (activatorLoader != null)
{
this._activatorLoader = activatorLoader;
}
else
{
this._activatorLoader = a => {
// old config code here...
}
}
}
The problem is that Autofac is seeing my request for a list of something and always providing the function. I tried switching to a delegate and get the same problem:
public delegate IList<Activator> ActivatorLoader(Input input);
public MyClass(
ActivatorLoader activatorLoader = null,
ConfigFile config = null)
{
if (activatorLoader != null)
{
this._activatorLoader = activatorLoader;
}
else
{
this._activatorLoader = a => {
// old config code here...
}
}
}
The loading of the activators must still be delayed, I'd like the flexibility of registering any function based on the situation, and old code (without an activator loader registered) should still work. Is there any way to prevent Autofac from autogenerating the Func?
The class will be instantiated through dependency injection in another class. At a later time, the activator loading code will be triggered (if needed).
var myObject = conatiner.Resolve<MyClass>();
// time passes...
myObject.DoActivatorLoading();
The primary goal is to prevent Autofac from creating the Func<Input, IList<Activator>> if it is not explicitly set. Is this possible?
Perhaps, it will be easier to create a separate class for activator loading ?
public class ActivatorsLoader
{
public IList<Activator> Load(Input input)
{
///
}
}
///
public Class(
ActivatorsLoader activatorsLoader = null,
ConfigFile config = null)
{
///
}
But it would be good to see the use cases of your Class.

object instantiation - mvc simultaneous connections

This is a pretty basic question but just want help understanding how a server interacts with the browser/computer connecting to it.
When a user hits the Create() action it sends the Currentclaim object to the view. Because the _currentclaim variable is null it creates a new object with certain properties. If I load up another browser (IE, Safari) and use the app it isn't a 'fresh start' as _currentclaim has retained the properties that were given to it in the other browser.
public class ClaimsController : Controller
{
private static ClaimViewModel _currentclaim;
private static ClaimViewModel Currentclaim
{
get
{//If _currentclaim is null then create it. Return it.
if (_currentclaim == null)
_currentclaim = GetClaimViewModel();
return _currentclaim;
}
set//set value of Currentclaim.
{
_currentclaim = value;
}
}
public static ClaimViewModel GetClaimViewModel()
{
return new ClaimViewModel()
{
ClaimID = 101,
SubmissionUserID = 10,
DateSubmitted = DateTime.Now,
LineViewModels = new List<LineViewModel>() {
new LineViewModel() {MeetingDate=DateTime.Now,SubCatID=1},
}
};
}
public ActionResult Create()
{
return View(Currentclaim);
}
[HttpPost]
public ActionResult Create(ClaimViewModel claimvm)
{ claimvm.SubmissionUserID = Currentclaim.SubmissionUserID;
claimvm.DateSubmitted = Currentclaim.DateSubmitted;
_currentclaim = claimvm;
return View("Summary", Currentclaim);
}
}
I just want to be reasssured that when a user connects to my web application from wherever it is hosted that his or her session will start with a null object (and not one instantiated by someone else .... if that makes sense)

Windsor Interceptor Exception

I have a Windsor container that I'm using an InterceptorSelector and a LazyComponentLoader with.
My InterceptorSelector returns an InterceptorReference to my InterceptorAdapter class that looks like this
public class InterceptorAdapter<T> : Castle.DynamicProxy.IInterceptor, IOnBehalfAware where T : IMyType
{
private readonly T interceptor;
public InterceptorAdapter(T interceptor)
{
this.interceptor = interceptor;
}
....
}
so the InterceptorSelector does
public InterceptorReference[] SelectInterceptors(ComponentModel model, InterceptorReference[] interceptors)
{
var results = new List<InterceptorReference>();
....
foreach (var interceptorType in someInterceptorTypes)
{
Type interceptorAdapterType = typeof(InterceptorAdapter<>).MakeGenericType(interceptorType);
if (kernel.GetHandler(interceptorAdapterType) == null)
{
// need to do this or Castle complains it can't create my
// interceptor...I guess LazyComponentLoaders don't work for InterceptorReferences?...
// I suspect the problem may be here...
kernel.Register(lazyComponentLoader.Load(null, interceptorAdapterType, null));
}
results.Add(InterceptorReference.ForType(interceptorAdapterType));
}
return results.ToArray();
}
Things work great the first time my InterceptorSelector returns an InterceptorReference. The next time, when it returns an InterceptorReference to an InterceptorAdapter with a different generic type argument, I get
Castle.MicroKernel.ComponentRegistrationException occurred
Message=There is a component already registered for the given key interceptor
Source=Castle.Windsor
StackTrace:
at Castle.MicroKernel.SubSystems.Naming.DefaultNamingSubSystem.Register(String key, IHandler handler) in c:\TeamCity\buildAgent\work\1ab5e0b25b145b19\src\Castle.Windsor\MicroKernel\SubSystems\Naming\DefaultNamingSubSystem.cs:line 75
InnerException:
My LazyComponentLoader simply does
public IRegistration Load(string key, Type service, IDictionary arguments)
{
ComponentRegistration<object> component = Component.For(service).Named(key);
if (arguments != null)
{
// merge is an extension method to merge dictionaries.
component.DynamicParameters((k, d) => d.Merge(arguments));
}
return component;
}
My container setup looks like
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.AddFacility("factories", new FactorySupportFacility());
container.Register(Component.For<ILazyComponentLoader>().ImplementedBy<MyLazyComponentLoader>().LifeStyle.Singleton);
container.Kernel.ProxyFactory.AddInterceptorSelector(new InterceptorSelector(container.Kernel, container.Resolve<ILazyComponentLoader>()));
Any suggestions?
Thanks!
This seems to be a problem in the way Castle resolves Interceptors using an LazyComponentLoader.
Changing my code in the selector to do:
if (kernel.GetHandler(interceptorType) == null)
{
// need to do this or Castle complains it can't create my
// interceptor...I guess LazyComponentLoaders don't work for InterceptorReferences?...
// I suspect the problem may be here...
kernel.Register(lazyComponentLoader.Load(null, interceptorType, null));
}
Type interceptorAdapterType = typeof(InterceptorAdapter<>).MakeGenericType(interceptorType);
if (kernel.GetHandler(interceptorAdapterType) == null)
{
// need to do this or Castle complains it can't create my
// interceptor...I guess LazyComponentLoaders don't work for InterceptorReferences?...
// I suspect the problem may be here...
kernel.Register(lazyComponentLoader.Load(null, interceptorAdapterType, null));
}
Seems to fix the problem.

How do I convert an HttpRequestBase into an HttpRequest object?

inside my ASP.NET MVC controller, I've got a method that requires an HttpRequest object. All I have access to is an HttpRequestBase object.
Is there anyway I can somehow convert this?
What can/should I do??
You should always use HttpRequestBase and HttpResponseBase in your application as opposed to the concrete versions which are impossible to test (without typemock or some other magic).
Simply use the HttpRequestWrapper class to convert as shown below.
var httpRequestBase = new HttpRequestWrapper(Context.Request);
Is it your method, so you can re-write it to take HttpRequestBase? If not, you can always get the current HttpRequest from HttpContext.Current.HttpRequest to pass on. However, I often wrap access to the HttpContext inside a class like mentioned in ASP.NET: Removing System.Web Dependencies for better unit testing support.
You can just use
System.Web.HttpContext.Current.Request
The key here is that you need the full namespace to get to the "correct" HttpContext.
I know it's been 4 years since this question was asked, but if this will help somebody, then here you go!
(Edit: I see that Kevin Hakanson already gave this answer...so hopefully my response will help those people who just read answers and not comments.) :)
To get HttpRequest in ASP.NET MVC4 .NET 4.5, you can do the following:
this.HttpContext.ApplicationInstance.Context.Request
Try to use/create a HttpRequestWrapper using your HttpRequestBase.
Typically when you need to access the HttpContext property in a controller action, there is something you can do better design wise.
For example, if you need to access the current user, give your action method a parameter of type IPrincipal, which you populate with an Attribute and mock as you wish when testing. For a small example on how, see this blog post, and specifically point 7.
There is no way to convert between these types.
We had a similar case. We rewrote our classes/web services methods so that they use HttpContextBase, HttpApplicationStateBase, HttpServerUtilityBase, HttpSessionStateBase... instead of the types of close name without the "Base" suffix (HttpContext, ... HttpSessionState). They are a lot easier to handle with home-made mocking.
I feel sorry you couldn't do it.
This is an ASP.Net MVC 3.0 AsyncController which accepts requests, converts the inbound HttpRequestBase MVC object to a System.Web.HttpWebRequest. It then sends the request asynchronously. When the response comes back, it converts the System.Web.HttpWebResponse back into an MVC HttpResponseBase object which can be returned via the MVC controller.
To answer this question explicitly, I guess you'd only be interested in the BuildWebRequest() function. However, it demonstrates how to move through the whole pipeline - converting from BaseRequest > Request and then Response > BaseResponse. I thought sharing both would be useful.
Through these classes, you can have an MVC server which acts as a web proxy.
Hope this helps!
Controller:
[HandleError]
public class MyProxy : AsyncController
{
[HttpGet]
public void RedirectAsync()
{
AsyncManager.OutstandingOperations.Increment();
var hubBroker = new RequestBroker();
hubBroker.BrokerCompleted += (sender, e) =>
{
this.AsyncManager.Parameters["brokered"] = e.Response;
this.AsyncManager.OutstandingOperations.Decrement();
};
hubBroker.BrokerAsync(this.Request, redirectTo);
}
public ActionResult RedirectCompleted(HttpWebResponse brokered)
{
RequestBroker.BuildControllerResponse(this.Response, brokered);
return new HttpStatusCodeResult(Response.StatusCode);
}
}
This is the proxy class which does the heavy lifting:
namespace MyProxy
{
/// <summary>
/// Asynchronous operation to proxy or "broker" a request via MVC
/// </summary>
internal class RequestBroker
{
/*
* HttpWebRequest is a little protective, and if we do a straight copy of header information we will get ArgumentException for a set of 'restricted'
* headers which either can't be set or need to be set on other interfaces. This is a complete list of restricted headers.
*/
private static readonly string[] RestrictedHeaders = new string[] { "Accept", "Connection", "Content-Length", "Content-Type", "Date", "Expect", "Host", "If-Modified-Since", "Range", "Referer", "Transfer-Encoding", "User-Agent", "Proxy-Connection" };
internal class BrokerEventArgs : EventArgs
{
public DateTime StartTime { get; set; }
public HttpWebResponse Response { get; set; }
}
public delegate void BrokerEventHandler(object sender, BrokerEventArgs e);
public event BrokerEventHandler BrokerCompleted;
public void BrokerAsync(HttpRequestBase requestToBroker, string redirectToUrl)
{
var httpRequest = BuildWebRequest(requestToBroker, redirectToUrl);
var brokerTask = new Task(() => this.DoBroker(httpRequest));
brokerTask.Start();
}
private void DoBroker(HttpWebRequest requestToBroker)
{
var startTime = DateTime.UtcNow;
HttpWebResponse response;
try
{
response = requestToBroker.GetResponse() as HttpWebResponse;
}
catch (WebException e)
{
Trace.TraceError("Broker Fail: " + e.ToString());
response = e.Response as HttpWebResponse;
}
var args = new BrokerEventArgs()
{
StartTime = startTime,
Response = response,
};
this.BrokerCompleted(this, args);
}
public static void BuildControllerResponse(HttpResponseBase httpResponseBase, HttpWebResponse brokeredResponse)
{
if (brokeredResponse == null)
{
PerfCounters.ErrorCounter.Increment();
throw new GriddleException("Failed to broker a response. Refer to logs for details.");
}
httpResponseBase.Charset = brokeredResponse.CharacterSet;
httpResponseBase.ContentType = brokeredResponse.ContentType;
foreach (Cookie cookie in brokeredResponse.Cookies)
{
httpResponseBase.Cookies.Add(CookieToHttpCookie(cookie));
}
foreach (var header in brokeredResponse.Headers.AllKeys
.Where(k => !k.Equals("Transfer-Encoding", StringComparison.InvariantCultureIgnoreCase)))
{
httpResponseBase.Headers.Add(header, brokeredResponse.Headers[header]);
}
httpResponseBase.StatusCode = (int)brokeredResponse.StatusCode;
httpResponseBase.StatusDescription = brokeredResponse.StatusDescription;
BridgeAndCloseStreams(brokeredResponse.GetResponseStream(), httpResponseBase.OutputStream);
}
private static HttpWebRequest BuildWebRequest(HttpRequestBase requestToBroker, string redirectToUrl)
{
var httpRequest = (HttpWebRequest)WebRequest.Create(redirectToUrl);
if (requestToBroker.Headers != null)
{
foreach (var header in requestToBroker.Headers.AllKeys)
{
if (RestrictedHeaders.Any(h => header.Equals(h, StringComparison.InvariantCultureIgnoreCase)))
{
continue;
}
httpRequest.Headers.Add(header, requestToBroker.Headers[header]);
}
}
httpRequest.Accept = string.Join(",", requestToBroker.AcceptTypes);
httpRequest.ContentType = requestToBroker.ContentType;
httpRequest.Method = requestToBroker.HttpMethod;
if (requestToBroker.UrlReferrer != null)
{
httpRequest.Referer = requestToBroker.UrlReferrer.AbsoluteUri;
}
httpRequest.UserAgent = requestToBroker.UserAgent;
/* This is a performance change which I like.
* If this is not explicitly set to null, the CLR will do a registry hit for each request to use the default proxy.
*/
httpRequest.Proxy = null;
if (requestToBroker.HttpMethod.Equals("POST", StringComparison.InvariantCultureIgnoreCase))
{
BridgeAndCloseStreams(requestToBroker.InputStream, httpRequest.GetRequestStream());
}
return httpRequest;
}
/// <summary>
/// Convert System.Net.Cookie into System.Web.HttpCookie
/// </summary>
private static HttpCookie CookieToHttpCookie(Cookie cookie)
{
HttpCookie httpCookie = new HttpCookie(cookie.Name);
foreach (string value in cookie.Value.Split('&'))
{
string[] val = value.Split('=');
httpCookie.Values.Add(val[0], val[1]);
}
httpCookie.Domain = cookie.Domain;
httpCookie.Expires = cookie.Expires;
httpCookie.HttpOnly = cookie.HttpOnly;
httpCookie.Path = cookie.Path;
httpCookie.Secure = cookie.Secure;
return httpCookie;
}
/// <summary>
/// Reads from stream into the to stream
/// </summary>
private static void BridgeAndCloseStreams(Stream from, Stream to)
{
try
{
int read;
do
{
read = from.ReadByte();
if (read != -1)
{
to.WriteByte((byte)read);
}
}
while (read != -1);
}
finally
{
from.Close();
to.Close();
}
}
}
}
It worked like Kevin said.
I'm using a static method to retrieve the HttpContext.Current.Request, and so always have a HttpRequest object for use when needed.
Here in Class Helper
public static HttpRequest GetRequest()
{
return HttpContext.Current.Request;
}
Here in Controller
if (AcessoModel.UsuarioLogado(Helper.GetRequest()))
Here in View
bool bUserLogado = ProjectNamespace.Models.AcessoModel.UsuarioLogado(
ProjectNamespace.Models.Helper.GetRequest()
);
if (bUserLogado == false) { Response.Redirect("/"); }
My Method UsuarioLogado
public static bool UsuarioLogado(HttpRequest Request)

Resources