How to avoid a HttpException when calling HttpContext.Request? - c#

So HttpContext.Request throws if called within a global start
public HttpRequest get_Request()
{
if (this.HideRequestResponse)
{
throw new HttpException(SR.GetString("Request_not_available"));
}
return this._request;
}
This is actually documented
ASP.NET will throw an exception if you try to use this property when the HttpRequest object is not available. For example, this would be true in the Application_Start method of the Global.asax file, or in a method that is called from the Application_Start method. At that time no HTTP request has been created yet.
Is there a way of checking if a HttpContext.Request is in a state that it can be retrieved without throwing the exception? Effectively I want to write a TryGetRequest helper method.
Reflection is not an option. It needs to be a public API.
I dont have access to the application context. this is generic logging code. So setting some flag when startup has finished is not an option

As deostroll observed, it is reasonable and may in fact be necessary to rely on the ASP.NET application lifecycle to determine when the current HttpRequest has become available. The generic logging code is presumably dependent at the very least on HttpContext.Current or some other reference to the current HttpContext instance. If that assumption holds true, then an HttpModule can be implemented that stores a flag in the HttpContext.Items collection when the BeginRequest event fires. The static TryGetRequest helper method can test for the presence of that flag to determine whether it is safe to use HttpContext.Request.
Perhaps like this:
public class HttpRequestHelper : IHttpModule
{
private const string HttpRequestIsAvailable = "HttpRequestIsAvailable";
public static bool TryGetRequest(HttpContext context, out HttpRequest request)
{
request = null;
if (context != null)
{
if (context.Items.Contains(HttpRequestIsAvailable))
request = context.Request;
}
return (request != null);
}
#region IHttpModule
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
}
private void context_BeginRequest(object sender, EventArgs e)
{
((HttpApplication)sender).Context.Items.Add(HttpRequestIsAvailable, true);
}
#endregion
}
The module must be registered in web.config (assuming IIS 7.0 integrated pipeline):
<system.webServer>
<modules>
<add name="HttpRequestHelper" type="Utility.HttpRequestHelper" />
</modules>
</system.webServer>
The logging code would use the helper method like this:
HttpRequest request;
if (HttpRequestHelper.TryGetRequest(HttpContext.Current, out request))
LogWithRequest(request, message);
else
LogWithoutRequest(message);
The implementation does not rely on private API's or reflection. It relies on a flag, but the state information remains with the HttpContext instance and is well encapsulated.

Why not wrap the call to HttpContext.Request with a try, catch block then you can catch the exception and modify your behaviour accordingly.

It is not possible without using reflection

Related

Does Private static variables gets shared with multiple sessions/user in web application?

I am having MVC web application in which i have written some code to get forms cookie..Some times when i log out automatically some other users name were gets displays in text-box for which i have never logged in.I believe its due to private static variable but not sure.I have below code that i have implemented can anyone help me for this.Thanks
////This is code i am using to set from cookie
private static string _formsCookieName;
private static string FormsCookieName
{
get
{
if (string.IsNullOrWhiteSpace(_formsCookieName))
{
_formsCookieName = FormsAuthentication.FormsCookieName;
}
return _formsCookieName;
}
}
private static string _formsCookiePath;
private static string FormsCookiePath
{
get
{
if (string.IsNullOrWhiteSpace(_formsCookiePath))
{
_formsCookiePath = FormsAuthentication.FormsCookiePath;
}
return _formsCookiePath;
}
}
public static UserSession LogoutAuthentication(HttpContextBase context)
{
UserSession session = null;
string cookieName = FormsCookieName;
try
{
HttpCookie httpCookie = context.Request.Cookies[cookieName];
httpCookie.Expires = DateTime.Now;
FormsAuthentication.SignOut();
}
catch
{
}
return session;
}
Yes, a static variable are shared amongst all threads.
Don't use static properties for values that should live only in the lifespam of your request. You can't even use [ThreadStatic] in asp.net because you don't control the thread pool, and the same thread can be reused to handle different requests .
And even when you DO want a static value that is mutated by different threads, you need to have locks in place to avoid race conditions.
Your FormCookieName class is request dependent, therefore it should only exist during the life spam of it. The poor man way of doing it would be to instantiate it in Application_BeginRequest and disposing it on Application_EndRequest of Global.aspx.cs, assuming .NET Framework 4.5.
The correct way of doing it, though, is using a DI container. They not only inject dependency, but manages the objects lifecycles. All major DI Containers have an HttpContext lifecycle manager of sorts, and .NET Core comes with a DI Container built in. In it, your code would become:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IFormsCookieName, FormsCookieName>();
}
And your controller:
public class FooController : ControllerBase
{
public FooController(IFormsCookieName formsCookieName)
{
// receives a FormsCookieName instance that can safely use it's non-static properties
}
}
EDIT: Full configuration of Unity would be too long and off-topic for stack overflow. But the basic idea is that the Dependency Injector Container will create an instance of a non-static FormsCookieName in the scope of your HttpContext and then dispose that and the end of the request. This ensures that every HttpContext gets it's own copy of FormsCookieNameand no data will mess up.
I recommend unity as DI Container. It's maintained by Microsoft, and it's performance has seen a lot of improvements in latest versions.
Configuring a DI Container isn't hard, and provides lots of benefits.

Global Error Handling in MVC 6

In my MVC 5 application unhandled exception are capture within the Global Application_Error event and then redirected to ErrorController.
The last error is added to HttpApplicationState in the Global.Error event and retrieved in the Controller.
MVC 6 doesn't have the Global file. it uses the IExceptionFilter in capturing the unhandled exception.
public class GlobalExceptionFilter : IExceptionFilter, IDisposable {
private readonly ILogger logger;
private bool _disposed;
public GlobalExceptionFilter(ILoggerFactory logger) {
if (logger == null) {
throw new ArgumentNullException(nameof(logger));
}
this.logger = logger.CreateLogger("Global Exception Filter");
}
public void OnException(ExceptionContext context) {
logger.LogError("GlobalExceptionFilter", context.Exception);
//redirect to controller
}
public void Dispose() {
if (this._disposed) {
return;
}
this._disposed = true;
}
private static int GetHttpStatusCode(Exception ex) {
if (ex is HttpResponseException) {
return (int)(ex as HttpResponseException).HttpStatusCode;
}
return (int)HttpStatusCode.InternalServerError;
}
}
Is it possible to do the same in OnException?
From asp.net core documentation (check here)
In general, filters are meant to handle cross-cutting business and
application concerns. This is often the same use case for middleware.
Filters are very similar to middleware in capability, but let you
scope that behavior and insert it into a location in your app where it
makes sense, such as before a view, or after model binding. Filters
are a part of MVC, and have access to its context and constructs. For
instance, middleware can’t easily detect whether model validation on a
request has generated errors, and respond accordingly, but a filter
can easily do so.
Based on explanation of this documentation. Both middle ware approach and filter approach will meet your requirements. If you need more information of MVC pipeline and its information of errors, you should use filter approach.

Have I Structure Map with Entity Framework constructed correctly with Context management in a wcf project

I have read other posts on this, and loads on net, but I am still unsure If what I have is fully correct..
I have use a servicehostfactory to initialise StructureMap in the appropriate service.. (based on this)
Snippet below..
public class StructureMapServiceHostFactory : ServiceHostFactory
{
public StructureMapServiceHostFactory()
{
Bootstrapper.ConfigureDependencies();
}
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new StructureMapServiceHost(serviceType, baseAddresses);
}
}
and the bootstrapping..
public static IContainer ConfigureDependencies()
{
if (AlreadyRegistered)
{
return ObjectFactory.Container;
}
lock (_lockThis)
{
if (AlreadyRegistered)
{
return ObjectFactory.Container;
}
BootstrapStructureMap();
AlreadyRegistered = true;
}
return ObjectFactory.Container;
}
public static void BootstrapStructureMap()
{
ObjectFactory.Initialize(x =>
{
x.AddRegistry<InfrastructureRegistry>();
});
}
public class InfrastructureRegistry : Registry
{
public InfrastructureRegistry()
{
For<Entities>().HybridHttpOrThreadLocalScoped().Use(c => new Entities());
...
The registering of my Entity Framework context is HybridHttpOrThreadLocalScoped. In the Application_EndRequest I am releasing http scoped objects which should be just the db context, as this I want per service request.
protected void Application_EndRequest(object sender, EventArgs e)
{
Bootstrapper.ReleaseAndDisposeAllHttpScopedObjects();
}
public static void ReleaseAndDisposeAllHttpScopedObjects()
{
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}
Is this the correct approach or am I missing something? This way I should not need a using statement around my context, as it should be scoped to that request, and the next request gets another one.
Main reason is that from time to time, when I access a sub object on an entity, the object is null, whereas it should nto be and I am trying to eliminate the fact that it might be a shared context..
I tried to write out the context on Application_EndRequest
var instance = StructureMap.ObjectFactory.GetInstance<AXA_Entities.Entities>(); - write to file then
and the hashCode was unique, but Calling GetInstance will get me a new instance each time I would imagine?
I think I am close on this, but an explanation of something I am possibly missing is appreciated.
Ideally I want my scope to be like this.
For<Entities>().HttpContextScoped().Use(c => new Entities());
but I get the following method as a result.
"StructureMap Exception Code: 309\nYou cannot use the HttpContextLifecycle outside of a web request. Try the HybridLifecycle instead."
unitofwork-in-wcf-using-structuremap answered what I should do.. there is other links inside so read carefully. I dont use the uow interface but the custom lifecycle is what I used in the end..
on version 2.6.4 of structuremap - latest version has changed some of the interfaces so havent upgraded yet.
For<Entities>().LifecycleIs(new WcfInstanceContextLifecycle()).Use(c
=> new Entities());

OnActionExecuting equivalent in standard asp.NET?

Is there an equivalent for MVC.NET's OnActionExecuting in standard asp.NET? ?
I thought it would be Page_Load since OnActionExecuting would be called each time an action is executed (or the page loads). But I'm running into inheritance issues when I try to use Page_Load instead.
Since it is very difficult to make my solution work with a Page_Load I'm thinking I might not have the best ... solution.
Any thoughts on whether they are equivalent or close enough?
Background:
I'm converting a piece of an MVC3 application into a standard .NET to wrap in a SharePoint Web Part.
Here's the MVC code I'm trying to translate, as you can see its the user security bits I'm translating:
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
if (!SiteCacheProvider.ItemCached(enmCacheKey.SiteSetting)) {
if (filterContext.IsImplementedGeneralPrincipal()) {
IUserProfile userProfile = ((IGeneralPrincipal)filterContext.HttpContext.User).UserProfile;
SiteCacheProvider.ChangeSiteSetting(userProfile.SiteID);
}
}
base.OnActionExecuting(filterContext);
}
First, take on account that no Actions are in ASP.NET because the model is different (Event-Based) - There're no methods(actions) which you can decorate with Action Filters, it's all about the Page-Cycle events.
Second, In ASP.NET, you may use HTTP modules (HttpApplication.BeginRequest particularly) in order to intercept incoming requests to your application pages by adding your required logic.
From MSDN:
HTTP Modules use to intercept HTTP requests for modifying or utilize
HTTP based requests according to needs like authentication,
authorization, session/state management, logging, modifying Response,
URL rewriting, Error handling, Caching....
For example:
using System;
using System.Web;
using System.Collections;
public class HelloWorldModule : IHttpModule
{
public string ModuleName
{
get { return "HelloWorldModule"; }
}
public void Init(HttpApplication application)
{
application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
application.EndRequest += (new EventHandler(this.Application_EndRequest));
}
private void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("<h1>HelloWorldModule: Beginning of Request</h1><hr>");
}
private void Application_EndRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("<hr><h1>HelloWorldModule: End of Request</h1>");
}
public void Dispose()
{
}
}

ASP.NET Override a webmethod

I have several WebMethods in a C# ASP.NET web app. I'd like to change the behavior of all of them to validate each request. Imagine the code below:
[WebMethod]
public static void DoSomething()
{
if (ValidateRequest())
{
HttpContext.Current.Response.StatusCode = 400;
// do some other stuff
return;
}
// rest of method
}
I've noticed of course that the ValidateRequest() method call is common to a large portion of my WebMethods. Is there anyway I can wire this up so that all WebMethods automatically have this same behavior? Could I add a second attribute to the method to accomplish this?
Add the validate request in the Begin Request of your Global.asax file.
Now, you need some sort of code to check if the request should be validated.
I'm unsure how to do this in webforms... But, what I'd do is:
use the RequestPath property (and get the method and class name if they match your service URL)
HttpContext.Current.Request.Path;
Then I would create a method attribute and perhaps use reflection to see if the request should be validated. (see link below)
http://msdn.microsoft.com/en-us/library/z919e8tw.aspx
This way from this point on you just need to tag your method with your "[Validate]" attribute and it all should just work.
public class Global : HttpApplication
{
protected void Application_BeginRequest(object sender, EventArgs e)
{
if(ShouldValidate() && !IsValidRequest()){
//add your custom error status here perhaps
Response.StatusCode = 400
Response.StatusDescription = "Something Bad happened"
HttpContext.Current.Response.End()
}
}

Categories

Resources