im building a high traffic asp.net webforms site. I have componentized all the urls in a class. When looking up the current route of the request what is most efficient? Calling HttpContext.Current.Request.RequestContext.RouteData.Route or sending Page.RouteData.Route into the method that checks to see if we are at a certain route url. Example:
public static bool IsCurrentRoute(string routeName)
{
var route = HttpContext.Current.Request.RequestContext.RouteData.Route;
if (route == System.Web.Routing.RouteTable.Routes[routeName])
return true;
return false;
}
Page.Routedata just wraps around Context.RouteData.
Taken from JustDecompile
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Browsable(false)]
public RouteData RouteData
{
get
{
if (base.Context != null && base.Context.Request != null)
{
return base.Context.Request.RequestContext.RouteData;
}
return null;
}
}
So to answer your Question - no difference. Though you are less likely to get an exception if you use the Page method due to null checks. Though how often your context is going to be null is another question and is possibly a case you want to design for yourself if you think it has potential.
Also rather than accessing HttpContext.Current directly think about wrapping it in a HttpContextBase and using that.
An example can be found here http://www.agileatwork.com/bolt-on-multi-tenancy-in-asp-net-mvc-with-unity-and-nhibernate/ look at the line with
new HttpContextWrapper(HttpContext.Current)
Related
I know there are lots of (answered) questions relating to attribute-based routing, but I can't seem to find one which answers my particular scenario.
I've got a WebAPI 2 controller, with a few methods using the default routing:
public Dictionary<int, SensorModel> Get()
{
return SensorModel.List();
}
public SensorModel Get(int id)
{
return SensorModel.Get(id);
}
[HttpPost]
public SensorModel Post(SensorModel model)
{
if (model == null) throw new Exception("model cannot be null");
if (model.Id <= 0) throw new Exception("Id must be set");
return SensorModel.Update(model.Id, model);
}
These all work fine. I'm trying to create a nested route as below:
[Route("sensor/{id}/suspend")]
public SensorModel Suspend(int id, DateTime restartAt, EnSite site)
{
return SensorModel.Suspend(id, restartAt, site);
}
For which I would expect the URL to look like:
http://[application_root]/api/sensor/1/suspend?restartAt={someDateTime}&site={anInt}
Sorry, forgot to say that the actual issue is a 404!
Can anyone tell me what I'm doing wrong? I know that I can do it like this:
[Route("sensor/suspend")]
public SensorModel Suspend(int id, DateTime restartAt, EnSite site)
{
return SensorModel.Suspend(id, restartAt, site);
}
Which makes the URL:
http://[application_root]/api/sensor/suspend?id=1&restartAt={someDateTime}&site={anInt}
But a cleaner API design seems to be a nested route, I think.
Your assumption is wrong in this point:
For which I would expect the URL to look like:
http://[application_root]/api/sensor/1/suspend?restartAt={someDateTime}&site={anInt}
It should be something like below:
http://[application_root]/sensor/1/suspend?id=1&restartAt={someDateTime}&site={anInt}
When you specify an attribute based routing, it overrides the default routing architecture of ../api/.. (or whatever you specify in route.config file).
So, whenever you try to use attribute based routing, you should do something like /route_prefix_at_controller_level/route_prefix_at_method_level.
We are running a very large web application in asp.net MVC .NET 4.0. Recently we had an audit done and the performance team says that there were a lot of null reference exceptions.
So I started investigating it from the dumps and event viewer.
My understanding was as follows:
We are using Asyn Tasks in our controllers. We rely on HttpContext.Current.Items hashtable to store a lot of Application level values.
Task<Articles>.Factory.StartNew(() =>
{
System.Web.HttpContext.Current = ControllerContext.HttpContext.ApplicationInstance.Context;
var service = new ArticlesService(page);
return service.GetArticles();
}).ContinueWith(t => SetResult(t, "articles"));
So we are copying the context object onto the new thread that is spawned from Task factory. This context.Items is used again in the thread wherever necessary.
Say for ex:
public class SomeClass
{
internal static int StreamID
{
get
{
if (HttpContext.Current != null)
{
return (int)HttpContext.Current.Items["StreamID"];
}
else
{
return DEFAULT_STREAM_ID;
}
}
}
This runs fine as long as number of parallel requests are optimal. My questions are as follows:
1. When the load is more and there are too many parallel requests, I notice that HttpContext.Current.Items is empty. I am not able to figure out a reason for this and this causes all the null reference exceptions.
2. How do we make sure it is not null ? Any workaround if present ?
NOTE: I read through in StackOverflow and people have questions like HttpContext.Current is null - but in my case it is not null and its empty. I was reading one more article where the author says that sometimes request object is terminated and it may cause problems since dispose is already called on objects. I am doing a copy of Context object - its just a shallow copy and not a deep copy.
Your problem is that a instance members of the HttpContext are not thread safe:
Any public static (Shared in Visual Basic) members of this type are
thread safe. Any instance members are not guaranteed to be thread
safe.
When accessing it the way you are doing (multiple threads) you need to do your own synchronization.
static object locker = new object();
get
{
lock (locker)
{
if (HttpContext.Current != null)
{
return (int)HttpContext.Current.Items["StreamID"];
}
else
{
return DEFAULT_STREAM_ID;
}
}
}
MSDN: system.web.httpcontext
Maybe I'm misreading this, but I'm getting the impression that you're only trying to prevent the null reference error.
public class SomeClass
{
internal static int StreamID
{
get
{
int returnValue;
if (HttpContext.Current != null)
{
if(HttpContext.Current.Items["StreamID"] != null)
{
returnValue = (int)HttpContext.Current.Items["StreamID"];
}
else
{
returnValue = DEFAULT_STREAM_ID;
}
}
else
{
returnValue = DEFAULT_STREAM_ID;
}
return returnValue;
}
}
}
I have an asp.net web site with our own DbResourceProvider. The plan was to localize pages with regular markup for resources: Text="<%$ Resources: Someword %>".
The provider returns the resourceKey if a resource is missing in the database so missing resources are ok at run-time. However at compile-time missing resources causes build-errors.
Does anyone have a workaround for this?
(I'll add more details about my attempts if needed.)
A collegue pointed out at a solution in the last comment in the blog-post linked to in the question. I don't have access to try it, but this class should solve the problem:
public class MyResources : System.Web.Compilation.IResourceProvider
{
private static string _entryMethod;
System.Resources.IResourceReader System.Web.Compilation.IResourceProvider.ResourceReader { get { throw new NotImplementedException(); } }
object System.Web.Compilation.IResourceProvider.GetObject(string resourceKey, System.Globalization.CultureInfo culture)
{
if (ASPNetCompilerExecutionContext)
return "ASPNetCompilerDesignTimeExecutionContext";
return "TODO: return actual resource";
}
static bool ASPNetCompilerExecutionContext
{
get
{
if (_entryMethod == null)
_entryMethod = (new StackTrace()).GetFrame((new StackTrace()).FrameCount - 1).GetMethod().Name;
if (_entryMethod == "PrecompileApp")
return true;
else
return false;
}
}
}
I guess an even simpler way would be to pretend all resources are present and return "missing" for missing resources.
I have a static class with several static methods. In these methods, I'm trying to access the current thread's context using HttpContext.Current. For example:
var userName = HttpContext.Current.User.Identity.Name;
However, when I do that, I receive a NullReferenceException, the infamous "Object reference not set to an instance of an object."
Any ideas?
It isn't clear from the original post that the HttpContext is actually what's missing. The HttpContext.User property can also be null at certain stages of the lifecycle, which would give you the exact same exception. All other issues aside, you need to step through the source and see which part of the expression is actually null.
When you write code that references static methods/properties like HttpContext.Current, you have to write them knowing that your code isn't guaranteed to be run when the methods/properties are actually available. Normally you have something like this:
static string GetCurrentUserName()
{
HttpContext context = HttpContext.Current;
if (context == null)
return null;
IPrincipal user = context.User;
if (user == null)
return null;
return user.Identity.Name;
}
Although I suspect that this wouldn't really solve your problem here, it would just get rid of the exception. The issue is more likely that you're calling this method at a time or place when the context is simply not available, such as on a background thread, static constructor or field initializer, or in the Application_BeginRequest method, or some similar place.
I might start by changing the static methods to instance methods of a class that depends on an HttpContext instance (i.e. taken in the constructor). It's easy to fool yourself into thinking that methods like GetCurrentUserName are simple "utility" methods, but they're really not, and it is generally invalid to be invoking a method that references HttpContext.Current through the static property from any place where you don't already have an instance reference to the same HttpContext (i.e. from the Page class). Odds are, if you start rewriting your classes like this:
public class UserResolver
{
private HttpContext context;
public UserResolver(HttpContext context)
{
if (context == null)
throw new ArgumentNullException("context");
this.context = context;
}
public string GetUserName()
{
return (context.User != null) ? context.User.Identity.Name : null;
}
}
...then you will likely find out very quickly where the chain is being broken, which will be the point at which you need to reference HttpContext.Current because you can't get it from anywhere else.
In this specific case, obviously, you can solve the problem just by taking the stack trace of the NullReferenceException to find out where/when the chain begins, so you don't have to make the changes I've described above - I'm simply recommending a general approach that will help reduce these sorts of "missing singleton" errors in the future.
I've run into this a few times, especially with static methods in another library and not my main project. I've resorted to passing the HttpContext to the static method as a param when nothing else seems to work.
Where exactly is the null exception being thrown? Have you debug and see what is null? Is the HttpContext.Current is null or the User?
Let's say I have the following interceptor in a SEAM app:
public class MyInterceptor {
#In
private Monitor myMonitor;
#AroundInvoke
public Object aroundInvoke(InvocationContext ctx) throws Exception {
try {
myMonitor.a();
return ctx.proceed();
}
finally {
myMonitor.b();
}
}
}
myMonitor.a() works (so Monitor is correctly injected), myMonitor.b() fails because Monitor is already null. Seam Doc says: "Injected values are disinjected (i.e., set to null) immediately after method completion and outjection."
Is that what is happening? Can I do something to tell SEAM to "not yet" "disinject" the component? I can of course also do something like XContext.get(..), but I'm wondering whether this is a bug or a mistake from my side. thanks!
Try this one instead
Object response = null;
try {
myMonitor.a();
response = ctx.proceed();
} finally {
myMonitor.b();
}
return response;
regards,
Avoid using injection.
Try working around this problem. I see you have some sort of monitoring going on. Look at this interceptor that captures the amount of time a method is executed in Seam components. Try modifying your code to match that.
It works great!
Here is the link
Seam is working as advertised.
You could just ignore the disinjection:
public class MyInterceptor {
private Monitor myMonitor;
#In
private void setMonitor(Monitor aMonitor) {
if (aMonitor != null) {
myMonitor = aMonitor;
}
}
#AroundInvoke
public Object aroundInvoke(InvocationContext ctx) throws Exception {
try {
myMonitor.a();
return ctx.proceed();
}
finally {
myMonitor.b();
myMonitor = null; //perform disinjection yourself
}
}
}
The caveat here is that Seam is disinjecting the reference for a reason. Seam wants to control the lifecycle and identity of "myMonitor" and by keeping a reference to it, you are not abiding by your contract with Seam. This could lead to unexpected behavior.
For instance, if myMonitor were for some reason in the Stateless scope, Seam might destroy it before ctx.proceed() returns, leaving you with a reference to a broken proxy. Best advice is to know the scope and lifecycle of what you are retaining since you are "living on the edge."