Getting the Server in Global.asax in ASP.NET MVC 4 - asp.net

When our ASP.NET MVC 4 app starts, we need to set a property on a Log4Net Appender which depends on what the site is.
Is there a way to get the 'http://www.site.com' part some time in the sites initial load, perhaps in Global.asax?
Overview:
If the server is www.site2.com then set the Appender.SomeValue = "555"
If the server is www.site.com then set the Appender.SomeValue = "123"
Because many sites will point to the same code base we don't know what we need to set Appender.SomeValue to until it runs.

I think methods in Global.asax would run, only in response to a request. And almost everywhere inside the ASP.NET, you have access to HttpContext.Current.Request.Url.
Also there is a method that runs way before Application_Start, and that is a method decorated with PreApplicationStartMethodAttribute attribute.
One approach is to use WMI (Windows Management Instrumentation) to get access to the current website, it's bindings and thus the site address.

Pre-application start is more limited as it is run before the application is started, more for initializing di containers. To be safe I would put the code in a new static method defined in global.asax.cs that is called by application_start method at this point access to HttpContext.Current.request.Url should be safe

Related

What code whould be placed in the application_start and the session_start events in global.asax?

Can you give an example of what might be best suited to place in the Application_Start and Session_Start subroutines?
I know when each subroutine is called.
Application_Start when the first user first accesses the web application.
Session_Start when a user opens a session with the application.
But what code belongs in each of these subroutines. What should the code in each subroutine do?
Just any examples? Well, in an MVC site the routes are registered in Application_Start. That's also a good place to initialize an IoC container such as StructureMap. Maybe initialize some singletons you have in your application if you want them to be readily available rather than late-bound when a user accesses them (like if they have a high initialization cost and you'd rather do one slow initial hit on the website yourself than bother a customer or two with it).
Session_Start is generally used less often, but could be a good place for per-user (or per-session, realistically) tracking of some kind.
Application_Start is often used to initialize application wide settings which need to be done once per application domain like registering object containers, reading some config initialization values, ... In Session_Start you could place some code which is tied to the specific user who started the session.
Be careful with exception handling in Application_Start. In IIS7 Integrated mode you won't have the response object or HTTPContext. See this thread: Request is not available in this context

Calling a method in an ASP.NET application from a Windows application

Other than using a web service, is there anyway to call a method in a web app from a windows application? Both run on the same machine.
I basically want to schedule a job to run a windows app which updates some file (for a bayesian spam filter), then I want to notify the web app to reload that file.
I know this can be done in other ways but I'm curious to know whether it's possible anyway.
You can make your windows app connect to the web app and do a GET in a page that responds by reloading your file, I don't think it is strictly necessary to use a web service. This way you can also make it happen from a web browser.
A Web Service is the "right" way if you want them to communicate directly. However, I've found it easier in some situations to coordinate via database records. For example, my web app has bulk email capability. To make it work, the web app just leaves a database record behind specifying the email to be sent. The WinApp scans periodically for these records and, when it finds one with an "unprocessed" status, it takes the appropriate action. This works like a charm for me in a very high volume environment.
You cannot quite do this in the other direction only because web apps don't generally sit around in a timing loop (there are ways around this but they aren't worth the effort). Thus, you'll require some type of initiating action to let the web app know when to reload the file. To do this, you could use the following code to do a GET on a page:
WebRequest wrContent = WebRequest.Create("http://www.yourUrl.com/yourpage.aspx");
Stream objStream = wrContent.GetResponse().GetResponseStream();
// I don't think you'll need the stream Reader but I include it for completeness
StreamReader objStreamReader = new StreamReader(objStream);
You'll then reload the file in the PageLoad method whenever this page is opened.
How is the web application loading the file? If you were using a dependency on the Cache object, then simply updating the file will invalidate the Cache entry, causing your code to reload that entry when it is found to be null (or based on the "invalidated" event).
Otherwise, I don't know how you would notify the application to update the file.
An ASP.NET application only exists as an instance to serve a request. This is why web services are an easy way to handle this - the application has been instantiated to serve the service request. If you could be sure the instance existed and got a handle to it, you could use remoting. But without having a concrete handle to an instance of the application, you can't invoke the method directly.
There's plenty of other ways to communicate. You could use a database or some other kind of list which both applications poll and update periodically. There are plenty of asynchronous MQ solutions out there.
So you'll create a page in your webapp specifically for this purpose. Use a Get request and pass in a url parameter. Then in the page_load event check for this paremter. if it exists then do your processing. By passing in the parameter you'll prevent accidental page loads that will cause the file to be uploaded and processed when you don't want it to be.
From the windows app make the url Get request by using the .Net HttpWebRequest. Example here: http://www.codeproject.com/KB/webservices/HttpWebRequest_Response.aspx

How to do something firstly when the asp.net server start

I need an interface that can be run firstly when the application start.
We can write some code in Application_Start of global.ascx.
Is there any other method to finish it after some configurations in web.config,i don't wanna write any code in global.ascx
You know,we can implement the Interface 'IHttpModule' to diy each request.
But the interface is not fix to application start.
which one is i wanna?
Thanks
A HttpModule is something that handles requests, and is not directly related to the lifetime of an application. Even if it's reusable, it may not survive during the whole lifetime of an application. The Global.asax file, on the other hand, becomes a subclass of HttpApplication, which indeed is a class that relates to the startup, shutdown and lifetime of a web application. According to MSDN, Global.asax is the file to put startup and shutdown code.
You can use the Init method of your module. It fires more or less around the same time as the Application_Start for the Global.asax.

ASP.NET - temporarily impersonate the app pool service ID when default it to impersonate the user?

I have to call some code in a SharePoint site that runs under the same service ID that the web application is running under. By default, SharePoint impersonates the user viewing the web page, and the users don't have the necessary permissions.
What is the best way to run some code using the web application's service ID, then revert back to using the default impersonation?
SPSecurity.RunWithElevatedPrivileges
Nat is right. You should use SPSecurity.RunWithElevatedPrivileges. Under the covers it does a ReverToSelf that Anthony mentions, but it is much easier to use the helper method. You can use an inline delegate as in the following example.
The main thing to realize is that this delegate runs under a separate application domain which basically means that you want to use a SPSite or SPWeb you must re-instantiate them within the delegate as shown below.
SPSecurity.RunWithElevatedPrivileges(delegate()
{
// Your are now inside the delegate
// Anything provided within this block is marshaled across the app domain
using (SPSite site = new SPSite("http://myserver/sites/mysite"))
{
using (SPWeb web= site.OpenWeb())
{
// Do stuff here
}
}
});
Under ASP I had a utility DLL that I could use to call Win32's RevertToSelf() function (found in the advapi32.dll) to get the ASP to run under the identity of the application pool.
Of course once there, there's no going back to the original identity the thread was using but that's not really a problem. Once the current request had ended, the next request would run again under the users identity (or the anonymous users).
You could probably do the same with PInvoke in ASP.NET but I wouldn't know what effect that might have on the framework. I'm certain it would last only for the current request. I don't think there is any standard .NET API to do this.
easy! Wrap the calls you're making in a HostingEnvironment.Impersonate() block.
http://msdn.microsoft.com/en-us/library/system.web.hosting.hostingenvironment.impersonate.aspx

IIS Integrated Request Processing Pipeline -- Modify Request

I want to implement an ISAPI filter like feature using HttpModule in IIS7 running under IIS Integrated Request Processing Pipeline mode.
The goal is to look at the incoming request at the Web Server level, and inject some custom HttpHeaders into the request. (for ex: HTTP\_EAUTH\_ID)
And later in the page lifecycle of an ASPX page, i should be able to use that variable as
string eauthId = Request.ServerVariables["HTTP\_EAUTH\_ID"].ToString();
So implementing this module at the Web Server level, is it possible to alter the ServerVariables collection ??
HttpRequest.ServerVariables Property is a read-only collection. So, you cannot directly modify that. I would suggest storing your custom data in httpcontext (or global application object or your database) from your httpmodule and then reading that shared value in the aspx page.
If you still want to modify server variables, there is a hack technique mentioned in this thread using Reflection.
I believe the server variables list only contains the headers sent from the browser to the server.
You won't be able to modify either the HttpRequest.Headers or the HttpRequest.ServerVariables collection. You will however be able to tack on your information to any of:
HttpContext.Current.Items
HttpContext.Current.Response.Headers
Unfortunately, Request.Params, Request.QueryString, Request.Cookies, Request.Form (and almost any other place you'd think of stuffing it is read only.
I'd strongly advise against using reflection if this is a HttpModule you're planning on installing into IIS 7. Given that this code will be called for (potentially) every request that goes through the web server it'll need to be really fast and reflection just isn't going to cut it (unless you have very few users).
Good luck!

Resources