Callling business logic layer method from PageMethods - asp.net

I've a static page method in web form application and I want to call method on private class level variable from it as shown below. I'm using jQuery to call the page method.
private readonly ICatalogBLL _catalogBLL = new CatalogBLL();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
_catalogBLL.GetSomething();
}
}
[WebMethod]
public static UpdateSomething(int i)
{
//Want to do as below. But can't call it from a static method.
_catalogBLL.UpdateSomething();
}
UPDATE
If I call it as said by John Saunders, won't it use the same instance for requests from different users as it is within a static method?

You can't. The page method is static. Your _catalogBLL is an instance member.
However, since you create a new instance of CatalogBLL on every request, why not do so once more?
[WebMethod]
public static UpdateSomething(int i)
{
CatalogBLL catalogBLL = new CatalogBLL();
catalogBLL.UpdateSomething();
}

You can't call because pagemethods are static...
A static method is simply one that is disassociated from any instance of its containing class. The more common alternative is an instance method, which is a method whose result is dependent on the state of a particular instance of the class it belongs to.
Look at John saunder's answer..

Related

accessing httpcontext properties from System.Timers.Timer

I have a problem when accessing httpcontext.current value at application_start method.
There is a lots of discussions about this topic.
But I want to share my business logic and I need some advice how to handle problem.
Let's look at this business logic together step by step
1-I want to design "custom object" which has "static global List" property and any user can add "LogObj" object to this list whereever actions occured.
public class MyLog
{
public static void List<LogObj> LogObjList {get;set;}
static MyLog()
{
LogObjList = new List<LogObj>();
}
}
2- If I have a "System.Timers.Timer" object which checks the "static global List" every X milliseconds and performs some action which defined in the code
public static init(){
System.Timers.Timer t = new System.Timers.Timer();
t.Elapsed += T_Elapsed;
t.Interval = 3000;
t.Start();
}
private void T_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//perform some code.
var s = HttpContext.Current.Session["test"];
var logObj = MyLog.LogObjList[0] + s;
//save as text file ...
}
3- If I start init() method in application_start event at global.asax I get this error "object reference ..." where the line of "..HttpContext.Current.Session" started.
So
If I do not want to access any httpcontext.current's properties I have no problem at this situation.
But If I need to access any properties of httpcontext.current at Timer_Elapsed event I have problem about it.
So I need your advice or alternative way to making my algorithm.
Thank you

IHttpModule is not being called for my WebMethod

Ok, so I have an existing application to which I have added a custom HttpModule. I'm registering two events in the Init() method (PreRequestHandlerExecute and PostRequestHandlerExecute). The HttpModule gets called for every 'normal' request. But not I have created an .aspx containing a few WebMethods that are being called for ajaxifying some UI components. The WebMethod gets called nicely, but the trouble is that my HttpModule does NOT get called at all (no events, no init, even no constructor) when accessing the WebMethod. The module gets called nicely when accessing the .aspx in question as a 'normal' request. But it refuses to be called when calling the WebMethod.
My .aspx looks like this:
public partial class SelectionListService : System.Web.UI.Page
{
[WebMethod]
[ScriptMethod]
public static RadComboBoxData GetItemsAsRadComboBoxData(RadComboBoxContext context)
{
...
}
}
My HttpModule look like this:
public class MyModule : IHttpModule, IRequiresSessionState
{
public MyModule ()
{
}
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += new EventHandler(Application_PreRequestHandlerExecute);
context.PostRequestHandlerExecute += new EventHandler(Application_PostRequestHandlerExecute);
}
private void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
...
}
private void Application_PostRequestHandlerExecute(object sender, EventArgs e)
{
...
}
}
I have been digging into this for quite some time now, but I just can't get it to work. Any ideas?
PS1: the BeginRequest, etc in global.asax.cs do get called when accessing the WebMethod.
PS2: I'm running IIS7 on Windows7.
since PageMethods must be static, an instance of the Page class with all it's events and the ASP.NET pipeline never happens. You simply get the result of your PageMethod call, and that is all.
I have a project that had the same problem. We found that the first event in the pipeline that we could get to fire for the WebMethods was the AcquireRequestState event. We hooked into that with our HttpModule in order to do the authorization checking required for the application.
I don't know what your pre and post request handlers do, but maybe you could shift some of the logic into the AcquireRequestState event handler.

Why does HttpContext.Current need to used within a class, but not a method

For instance if I'm inside the Page_Load method and I want to get query string data I just do this:
public partial class Product_Detail : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string id = Request.QueryString["p"];
}
}
but if I am inside the class, but not within any method I have to use:
public partial class Product_Detail : System.Web.UI.Page
{
string id = HttpContext.Current.Request.QueryString["p"];
protected void Page_Load(object sender, EventArgs e)
{
}
}
Why is that?
Member variable initialisers - which is what your id assignment is -- can't use instance methods or properties. Page.Request is an instance property, and therefore isn't available to member initialisers.
I would surmise it is because class members are not created until the class is instantated. Because of this you cannot access the Request property except within your class methods.
Properties of the current class (including this) are not accessible until the constructor. Since field initializers happen before the constructor is executed, properties (and fields, and methods) are not accessible.
You cannot refer to an instance's properties for a field's initializer—when the field is initialized the instance isn't fully constructed yet (i.e., there's no this pointer).

HttpContext Items Not Available to Web Method Called by AJAX

I have an item that I store in the HttpContext:
HttpContext.Current.Items["myItem"] = "123";
I can access this no problem from any of a page's methods. For example:
protected override void OnLoad(EventArgs e)
{
string l_myItemVal = HttpContext.Current.Items["myItem"] as string; // "123"
}
This works fine.
However, when calling one of the page's web methods via AJAX, this fails:
[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod]
public static string MyWebMethod()
{
string l_myItemVal = HttpContext.Current.Items["myItem"] as string; // NULL
}
Is the HttpContext of an asynchronous call different from the HttpContext for the page?
HttpContext.Items only holds items during a single request. Your AJAX request is a second request, and has it's own Items property.
Maybe you need to enable session state to make this work:
[System.Web.Services.WebMethod(true)]

Using Autofac with ASP.NET and the MVP pattern

I'm trying to integrate Autofac into an exsisting ASP.NET web application.
The pages follow the MVP pattern. Each page implements a View and delegate functionality to a Presenter. The View is injected into the Presenter thru the constructor.
I was able to register the Presenter and View and the page loads fine but when a postback happens the user controls on the view are null. It seems that Autofac creates a new instance of the Page to give to the presenter instead of giving it the instance real Page instance. Is there a way to have Page instances registered with Autofac?
Has anyone use Autofac with ASP.NET and MVP?
Thanks!
There is a better way. First, enable the Web integration module. This will enable automatic property injection into the Page instance.
Since your presenter needs the view in its constructor, your page should take a dependency on a presenter factory instead of the presenter itself.
So, first you need the presenter factory, which is a delegate with the necessary parameters:
public delegate IOCTestPresenter IOCTestPresenterFactory(IIOCTestView view);
This delegate must match the parameters (type and name) of the presenter constructor:
public class IOCTestPresenter
{
public IOCTestPresenter(IIOCTestView view)
{
}
}
In your view, add a property receiving the factory delegate, and use the delegate to create the presenter:
public partial class IOCTest
{
public IOCTestPresenterFactory PresenterFactory {get;set;}
protected void Page_Load(object sender, EventArgs e)
{
var presenter = PresenterFactory(this);
}
}
In your container setup you will have to make the following registrations:
builder.Register<IOCTestPresenter>().FactoryScoped();
builder.RegisterGeneratedFactory<IOCTestPresenterFactory>();
I figured out a solution. Basically, you would register the page instance during the Page_PreInit event and then call the container to inject the dependencies. Ex.
public partial class IOCTest : System.Web.UI.Page, IIOCTestView
{
protected void Page_PreInit(object sender, EventArgs e)
{
var containerProviderAccessor = (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance;
var containerProvider = containerProviderAccessor.ContainerProvider;
var builder = new ContainerBuilder();
builder.Register(this).ExternallyOwned().As<IIOCTestView>();
builder.Build(containerProvider.RequestContainer);
containerProvider.RequestContainer.InjectProperties(this);
}
public IOCTestPresenter Presenter { get; set; }
I'm not sure if there is a better way, but this seems to work.

Resources