I have a custom HttpModule implemented for a site I am working on. It is designed to perform an action on the PreSendRequestContent event. When I run the debugger and built in Visual Studio Server it runs without any problems. BUt when I publish it to the Live Server it doesn't. I am using a Classic Mode configuration of IIS meaning that I should only have to add the module to the web.config file. Am I missing something?
namespace SmartBilling
{
public class HttpModule : IHttpModule
{
public HttpModule()
{
}
public void Init(HttpApplication httpApplication)
{
// Register our event handler with Application object.
httpApplication.PreSendRequestContent += new EventHandler(httpApplication_PreSendRequestContent);
}
void httpApplication_PreSendRequestContent(object sender, EventArgs e)
{
// Do stuff
}
public void Dispose()
{
// Left blank because we dont have to do anything.
}
}
}
Related
I have a self hosted named pipes (not using http) wcf hosted in a class library. I am able to start the WCF by using the following method in the class library:
ServiceHost serviceHost;
public void startService()
{
// Create the service host
...
// Open Service Host
serviceHost.Open();
}
And then from a winforms test program running the following from a button click:
MyClassLib.MySvc testSvc;
private void button2_Click(object sender, EventArgs e)
{
testSvc = new MyClassLib.MySvc();
testSvc.startService();
}
This does correctly start the WCF running in the class library.
But this requires the winforms that is referencing the class library to call startService method.
What I would like is just to be able to start the service as soon as a reference to the class library that will be running the WCF is done.
I have attempted to add the following in the class library service's constructor:
public MySvc()
{
startService();
}
And then instantiate from the winforms:
MyClassLib.MySvc testSvc;
private void button2_Click(object sender, EventArgs e)
{
testSvc = new MyClassLib.MySvc();
//testSvc.startService(); //No need to call this
}
If I debug the code, I can see that in fact it does break at this point:
public MySvc()
{
startService(); // It does run this but service does not start
}
But this does not run the service. Any help would be appreciated.
Note #1: I believe its some type of timing issue where it does not let you start the service during the constructor method but not sure of that.
Problem resolved and yes my assumption that it was a timing issue (See Note# 1 above) was correct!
To replicate, change this:
public MySvc()
{
startService(); // It does run this but service does not start
}
To this and problem solved:
public void delayStartService()
{
Task.Delay(1000).ContinueWith(t => startService());
}
public MySvc()
{
delayStartService();
}
I'm using code first to develop my database for my MVC app. Here's the connection string:
<add name="OrtundWebConnectionString" connectionString="Data Source=.\SQLEXPRESS; Initial Catalog=OrtundWeb; User Id=sa; Password=sa;" providerName="System.Data.SqlClient"/>
It uses SQL Authentication because for reasons I've yet to determine, Windows Auth doesn't allow me to do anything on the server...
Here's Application_Start():
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
OrtundDB.InitializeDB();
}
This class calls db.Database.Initialize(true); and runs a method I wrote to add some default information into the database
public static class OrtundDB
{
private static OrtundDBContext db = new OrtundDBContext();
public static void InitializeDB()
{
db.Database.Initialize(true);
db.InitializeDB();
}
}
Here's the DBContext class I wrote that's being used. This exists in another project which is referenced in the MVC project:
internal class OrtundDBContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// modelBuilder.Configuration.Adds()
}
public OrtundDBContext()
: base("OrtundWebConnectionString")
{
Database.SetInitializer<OrtundDBContext>(new DropCreateDatabaseAlways<OrtundDBContext>());
}
public void InitializeDB()
{
// inserts the default data - an admin user account and information for user roles
}
// DbSet calls here
}
I've previously built an MVC app with this same methodology, and that one works. This, however, doesn't even execute Application_Start() every time.
On the odd occasion where it has executed Application_Start, it went all the way through to execute db.Database.Initialize(true); at which point, it just never seemed to end. I got no errors, but the action didn't seem to complete.
I'm a bit of a novice when it comes to MVC so I have no idea what the problem could be or how to fix it.
Any assistance to fix the problem (and possibly explanation as to what might cause it) will be greatly appreciated.
Thanks in advance!
Perhaps the issues lies with the expectation you have on Application_Start.
Application_Start is called once for the application being loaded into the app pool on IIS.
Only when the app pool is recycled or IIS is restarted will it be called again.
Take 10-15mins to read IIS pipeline
It will help with what is going on.
I had a nasty bug due to my false expectations about threads and requests.
alternatives to Consider and test in debug to see if they suit you:
The INIT in Global.asax
public override void Init() {
base.Init();
// handlers managed by ASP.Net during Forms authentication
BeginRequest += new EventHandler(BeginRequestHandler);
// PostAuthorizeRequest += new EventHandler(PostAuthHandler);
EndRequest += new EventHandler(EndRequestHandler);
}
Better: A single baseController for all your controllers so as to control bootstrap each call.
public class SomeController : MyBaseMvcController{
// whatever as usual....
}
[System.Web.Mvc.Authorize]
[MyMVCFilter] // see the filter below. Get the MVC pipeline to call your code on Executing
public abstract class MyBaseMvcController : Controller
{
protected MyBaseMvcController () {
// a place to get a NEW uow or new Context ....
}
}
public class MyMVCFilter : System.Web.Mvc.ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext) {
// a useful bootstrap option when you need the httpContext for bootstrap.
BootStrapHttp(filterContext.HttpContext);
base.OnActionExecuting(filterContext);
}
}
Is there a way to setup some default settings for webpages being ran on debug mode?
For example, I'd like to set a default session userid on debug mode, but trying this in Application_Start() causes errors:
protected void Application_Start()
{
#if DEBUG
Session["User"] = "1"
#endif
}
I could instead choose to place that in controllers, but that'd require a lot of code duplication.
The reason that this throws an error is because the Session object is associated with a request. There is no request in the Application_Start event. You could move this logic to the Application_AcquireRequestState event handler and it would work fine.
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
if (HttpContext.Current.IsDebuggingEnabled)
{
HttpContext.Current.Session["user"] = "1";
}
else
{
HttpContext.Current.Session["user"] = "0";
}
}
EDIT
After further research, I was mistaken. In the .NET pipeline, the above event handler is the first place that you can access the session object. It has not been retrieved from the server in the Application_BeginRequest which is why you are getting a NullReferenceException still. I tested the above code in MVC 5 and had no issues.
Also, instead of having to rely on compiler constants, you can easily tell if you are in debug mode or not using the above syntax of HttpContext.Current.IsDebuggingEnabled. This basically is a wrapper for checking the web.config attribute on the compilation tag and seeing if debug="true"
Note - You have to use the fully qualified name of HttpContext.Current.Session (as above) since the global event handlers do not have a direct inheritance of the current HttpContext.
You could use the Conditional attribute and put it on a method in your base controller. Something like this:
public class BaseController : Controller {
public BaseController() {
SetupDebugData();
}
[Conditional("DEBUG")]
public void SetupDebugData() {
Session["User"] = "1";
}
}
The call to SetupDebugData will be optimized away for Release builds. Then you just inherit from this controller in your other controllers:
public class AdminController : BaseController {
// ...
}
Yes, off-course.
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
#if(DEBUG)
Console.WriteLine("This is debug mode");
#else
Console.WriteLine("This is release mode");
#endif
base.OnActionExecuting(filterContext);
}
This code will be work in MVC ( I use it since MVC3). Remember that you need to set release build and debug false in web.config when you deploy your asp.net app on server.
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()
{
}
}
I have an website under which i have 5 files
test1.aspx
test2.aspx
test3.aspx
test4.aspx
test5.aspx
i have an http module which gets called in all the pages
but i have an condition where on test5.aspx page i do not want the http module to be called what settings need to be done in order to resolve the issue?
HttpModules get run before your page lifecycle, so you'd have to match it on the request path.
Assuming your HttpModule's Init function sets up a BeforeRequest handler, something like:
public class MyModule : IHttpModule
{
public void Init(HttpApplication application)
{
application.BeginRequest += this.BeginRequest;
}
public void BeginRequest(object sender, EventArgs e)
{
var app = sender as HttpApplication;
if (app.Request.Path.Contains("test5.aspx")) {
return;
}
// Process logic for other pages here
}
}