How to access my variables in a web method? - c#

I am using ASP.NET Webforms and in one page I want to make an AJAX call to a web method in the code behind. The problem is that web methods are static and I can't access page variables. I need to be able to have Ninject inject a dependency. Is there a way to do this in a web method?
public partial class Default : Ninject.Web.PageBase
{
[Inject]
public ISecurityController SecurityController { get; set; }
[WebMethod]
public static string DoSomething()
{
SecurityController.WriteToLog(); // Can't access SecurityController because it doesn't exist.
}
}
Since web methods are static it almost seems silly to even have it in the code behind for the page because it can't actually interact with the page. It's an isolated island in the code behind. Is there a better way to accomplish this? Or at the very least is there a way I can have Ninject inject ISecurityController into the web method somehow?
Thanks for the help.

You can directly retrieve it from the kernel using the IKernel.Get<T>() method:
[WebMethod]
public static string DoSomething()
{
NinjectModule module = new YourModule();
IKernel kernel = new StandardKernel(module);
var controller = kernel.Get<ISecurityController>();
controller.WriteToLog();
}

somwhere in your application is a singleton of Ninject. reference this singleton within the webmethod. a similar process is being do in Ninject.Web.PageBase.

Related

Where to put the Container?

I'm experimenting with IoC in my Web App and would like to do things according to best practices. Recently I discovered an IoC framework called DryIoc which is supposed to be small and fast.
I've read through the examples but none seem to point out where I should put the container itself.
Should it reside in the controller? Or in Global.asax? Someplace else maybe? Or perhaps as a static variable in a class?
I'd appreciate if someone would be able to guide me in the right direction, preferrably with some sample code, as I've stalled and don't got a clue on how to continue.
var container = new Container(); // Should obviously NOT be a local variable
container.Register<ISalesAgentRepository, SalesAgentRepository>(Reuse.Singleton);
Usually I do the following:
1 - Create a bootstrapper class
public static class Bootstrapper {
public static Container _container;
public void Bootstrap() {
var container = new Container;
// TODO: Register all types
_container = container;
}
public static T GetInstance<T>() {
return _container.Resolve<T>();
}
}
2 - Call the bootstrap method in the global.asax, in the Application_Start method:
protected void Application_Start() {
Bootstrapper.Bootstrap();
}
And never use the container anywhere directly, you have to hook it somewhere in the MVC lifecycle, and usually the DI package you use can do this for you.
Also note that I've added a GetInstance<T> method to the bootstrapper-class. This method is what makes it possible to use the container directly by requesting instances of types. I've added this method so you know it is possible, but always use constructor-injection if possible.
Actually, you may not need to store container on your side. Here is the DryIoc WebApi Owin sample.
The DryIoc.WebApi extension will store and Dispose the container when it is appropriate in IDependencyResolver implementation.

Calling a method of the ASPX page from Web Service

I have a simple Web Service with one method. (This method calling from another application)
In this method I need to call ASPX page of sided site - not html code, but method of this page.
Can anyone ask, how can I do this?
It is generally a good idea to have shared/reusable code stored separately from both the web service and the ASPX page so that any number of dependents may access it.
But to answer your question specifically:
I'll assume that the web service class is able to reference the ASPX page class (.aspx.cs or aspx.vb).
The example below shows two ways of accomplishing what you're asking. You can either instantiate your Page class and use the method just as you would any other normal class, or if the method is static, use it as is without instantiating your Page class.
Example:
public class MyAspxPage : Page
{
private Object _myObj = new object();
public object GetObject()
{
return _myObj;
}
public static object GetAnObject()
{
return new object();
}
}
public class MyWebService : WebService
{
public void MyWebServiceMethod1()
{
MyAspxPage page = new MyAspxPage();
object result = page.GetObject();
}
public void MyWebServiceMethod2()
{
object result = MyAspxPage.GetAnObject();
}
}
you don't want to be sharing code in aspx pages. You should create a project of type class library in your solution. Put your code that you want to be common code called from aspx pages and web services into the class project in a class.

Access Application global variable from WCF that runs asynchronously

I am trying to access global.asax application variable from WCF, that's my goal at least. I've tried many type of solutions, but the one that I am trying now is using static variables.
I've created a StaticVariable.cs class like so:
public static class StaticVariables
{
private static string _Key = "name1";
public static Object someInfo
{
get
{
return HttpContext.Current.Application[_Key];
}
}
}
The Application["name1"] is initialized in the global.asax.cs. I can read it when I access my webservice but not in my WCF service.
In my WCF I call the StaticVariables someInfo to retrieve the data, but I get:
System.Web.HttpContext.Current is null error
My WCF is running asynchronously and its called from within a webservice using Task<int>.Factory.FromAsync. So I assume that the problem is that the WCF runs not on the main thread, but I am not sure.
So it seems that the Static class doesn't work in my case and I wanted to know how to solve this. Thanks
Why don't you simply use static variables ?
HttpContext is dependent on ASP.NET pipeline. In a host-agnostic model (OWIN or self-hosted) you don't have access to it.
Application storage in HttpApplicationState is only useful if you need to access the current HttpContext. If it's not necessary, you should simply use static properties.
Moreover, HttpApplicationState was initially created for backward compatibility with classic ASP.
public static class StaticVariables
{
public static object SomeInfo { get; set; }
}
See also Singleton and HttpApplicationState and http://forums.asp.net/t/1574797.aspx

How to work around Response / Server which does not exist in the context?

I have this C# ASP.NET 4 website.
I would like to have a general method in a class which will include a Response.Redirect or Server.Transfer in it to a specific page.
Both names, Response and Server, does not exist in the context.
How to work this around?
as for the comment by #Maess, please consider something like this (edited):
ASPX:
<asp:Button onclick="MyClass.btnRedirect_Click" ID="btnMyButton" Text="MyButtonText" runat="server" />
Code behind:
public static void btnRedirect_Click(object sender, EventArgs e)
{
Response.Redirect("~/SomePage.aspx");
}
You'll find these as properties within HttpContext.Current
You can use System.Web.HttpContext.Current, but be careful. If there is no HTTP context at the time these methods are called you will get an exception.
It is probably safer to have these classes either require an HttpContext in the constructor or have the methods that require an HttpContext to have them in the method signature.
For instance, maybe you have a class which needs to redirect as you mentioned. Your method signature might look like this: public void CustomRedirect(HttpContext context) then within the body of your signature you would do something like this: context.Response.Redirect("..."). Basically, you make the class or method dependent upon having an HttpContext.
Don't directly reference anything involving the HTTP/IIS stack if you're ever going to be called outside of it.
Your best bet is probably to have your class or method accept either a delegate or an object that implements an interface provided by the calling code. When you're ready to redirect, call that delegate/interface method with the URI (or enough information to construct it) and then the calling code can respond with a server.transfer, a response.redirect or a passing unit test.
public static void ButtonRedirect()
{
MyClass foo = new MyClass(delegate(string s) { Server.Transfer(s); });
foo.DoThings();
}
public class MyClass
{
private Action<string> redirector;
public MyClass(Action<string> redirectAction)
{
redirector = redirectAction;
}
public void DoThings()
{
//Doing stuff
//Aha! this should redirect
redirector("/go/to/here");
}
}

HttpHandler, Unity, Dependency Injection (DI), web.config is it even possible?

public class MyHttpHandler : IHttpHandler
{
public MyHttpHandler() { ... }
public IUnityContainer Container { get; set; }
}
Is there a way to somehow get Container magically be set to a container I setup in global.asax?
Right now I can't find a way of doing it other than using AppDomain.CurrentDomain.GetData("container") as IUnityContainer.
Please let me know if there is a cleaner way of doing this.
First hit on google for asp.net mvc2 unity
http://weblogs.asp.net/shijuvarghese/archive/2010/05/07/dependency-injection-in-asp-net-mvc-nerddinner-app-using-unity-2-0.aspx
There are plenty of articles about MVC and Unity. You basically need to create a custom controller factory (in mvc2). MVC3 got a different solution.
Update
Use the BuildUp method in global.asax.
Sry. that was for existing objects. Why not just Register it and directly after Resolve it?
Singleton pattern may help you)
I would use service location instead.

Categories