Can an ASP.NET page be a WebService also? - asp.net

I know it's a little odd, specifically because a Page inherits from the System.Web.Page (or something) and a WebService inherits from System.Web.Service (or something).
But just thought I'd ask if there is any way to do this? Does anyone have suggestions to do this?
public class MyWebService : System.Web.Services.WebService
{
[WebMethod]
public String MyMethod()
{
return "";
}
}
public class MyWebPage : System.Web.UI.Page
{
protected void ExecuteButton_Click(Object sender, EventArgs e)
{
...
}
}

Not sure what you are looking for but you can have [WebMethod] as an attribute to your method on .aspx.cs page. I use it to execute this method from .aspx page.
ex:-
[WebMethod]
public static void YourMethod(string parameter)
{
}
From the code that you have posted thing I cannot see the static method on your page secondly I dont see the call in your service to the method.
try doing something like this
public static type MyMethodOnPage()
and the in your servie method call this static method.
public type MyMethodInService()
{
return MyPageName.MyMethodOnPage();
}

Yes we have. We can use AJAX callbacks.
Check this URL
http://geekswithblogs.net/frankw/archive/2008/03/13/asp.net-ajax-callbacks-to-web-methods-in-aspx-pages.aspx

Related

ExceptionFilters in WebAPI never get hit

I'm trying to catch errors coming from one of my controllers. Elmah is not catching them so in trying to find out why, I reduced the problem to the simplest form which excludes Elmah.
[HttpGet]
[Route("foo")]
public HttpResponseMessage Foo()
{
throw new Exception("test");
}
protected void Application_Start()
{
GlobalConfiguration.Configuration.Filters.Add(new UnhandledExceptionFilter());
GlobalConfiguration.Configure(WebApiConfig.Register);
public class UnhandledExceptionFilter : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context) {
dosomething(); //It never reaches here
Note: a proper JSON error is emitted to the client.
Instead of doing GlobalConfiguration.Configuration.Filters.Add, go to the Register method in the WebApiConfig class and do config.Filters.Add(new ...()); instead, that works for me.

Removing "X-Frame-Options" header for a specific controller only

I am trying to remove the "X-Frame-Options" header for only a specific controller's actions using:
protected override void OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.HttpContext.Response.Headers.Remove("X-Frame-Options");
base.OnResultExecuting(filterContext);
}
However, that doesn't seem to work at all. The only way I can get it to work at all on my site is to add this code to the global.asax below. I am pretty sure I am missing the correct step in the ASP.NET MVC / IIS pipeline that allows me to overwrite the IIS setting of that header. Is this possible?
protected void Application_EndRequest()
{
Response.Headers.Remove("X-Frame-Options");
}
As for why I want to do this, I am building a widget that user's will be able to use on their personal sites through the use of an iframe, but allow them to post back information to our site. I realize there are security implications to turning this header off, and while I welcome any suggestions on how to mitigate those risks, I just want to know if what I am asking is possible.
OnResultExecuting happens too early in the MVC lifecycle. The header has not been set yet.
What you need is the OnResultExecuted method which is run after the View is rendered.
Here's how you write a filter class for what you are looking for:
using System.Web.Mvc;
namespace Test.Filters
{
public class RemoveXFrameOptionsAttribute : ActionFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.Headers.Remove("X-Frame-Options");
base.OnResultExecuted(filterContext);
}
}
}
Then to use it, decorate whatever Controller or Action you want this filter applied.
[RemoveXFrameOptions]
public class TestController : Controller
{
public ActionResult Index()
{
return View();
}
}
or
public class TestController : Controller
{
[RemoveXFrameOptions]
public ActionResult Index()
{
return View();
}
}

ASP.NET is System.Web.UI.Page thread safe

I am wondering if the following code is thread safe?
Can i be be sure that UniqueFoo will indeed be the Unique Foo and will not be override?
public partial class Dummy : System.Web.UI.Page
{
public string UniqueFoo{ get; set; }
protected void Page_Load(object sender, EventArgs e)
{
var id = int.Parse(Request["Id"]);
UniqueFoo = SomeThreadSafeWCF.GetUniqueFoo(id);
}
}
what about the following (static)
public partial class Dummy : System.Web.UI.Page
{
public static string UniqueFoo{ get; set; }
protected void Page_Load(object sender, EventArgs e)
{
var id = int.Parse(Request["Id"]);
UniqueFoo = SomeThreadSafeWCF.GetUniqueFoo(id);
}
}
i later want to use UniqueFoo in a [WebMethod]
[WebMethod]
public static void SetSomeObject(SetSomeObject obj)
{
SomeThreadSafeWCF service = new SomeThreadSafeWCF ();
service.SetSomeObject(UniqueFoo, obj);
}
EDIT:
I am getting SetSomeObject from JS and UniqueFoo is coming from ASP.NET
will i have any issues when NOT using the static in my Dummy class according to your answers?
Surely your first sample is thread safe because when a request of a page post to the Web Server asp.net make new instance of your page and call page_load so if your SomeThreadSafeWCF.GetUniqueFoo() always make a unique Foo everything is thread save
Your second code snippet is not thread safe because you are modifying the value of a static field. So for example if later in this page you attempt to read the value of this UniqueFoo field you might not get the value you expect.
The first code snippet is fine because the field is not static.
If you want to use the UniqueFoo in a WebMethod then I would recommend you to pass it to this web method when calling it.
[WebMethod]
public static void SetSomeObject(SetSomeObject obj, string uniqueFoo)
{
SomeThreadSafeWCF service = new SomeThreadSafeWCF ();
service.SetSomeObject(uniqueFoo, obj);
}

ASP.NET MVC - Unit Testing Override Initialize Method

I've got an abstract class shown below which gets inherited by all the other controllers. Is it possible to test this method at all? Btw, I'm trying to use MOQ but no luck. If you could help me will be much appreciated:
public abstract class ApplicationController : Controller
{
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
//do some stuff here
}
}
If you take a look at the source code of base Initialize method you will find out that what it does is that it sets up ControllerContext and url stuff. Now, download MvcContrib TestHelper and check out TestControllerBuilder . The builder sets up everything you need in order to have controller context and other stuff which you depend upon.
Ok, we are not over yet - you wanted to test your own override of Initialize right?
TestControllerBuilder doesnt call your Initialize because it does initialization in different way. I suggest you to factor out your custom Initialize() logic out into different method. Then create fake (stub) subclass with public method that calls this factored out protected Initialize. Are you with me?
something like:
public abstract class ApplicationController : Controller
{
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
MyInitialzie()
}
protected void MyInitialize()
{
ControllerContext.XXX // do whatewer you want here. Context is already setted up
}
}
class FakeController: ApplicationController
{
public void CallMyInitialize()
{
MyInitialize();
}
}
Later in test class:
[Test]
public void MyInitializeTest()
{
TestControllerBuilder builder = new TestControllerBuilder();
FakeController controller = new FakeController();
builder.InitializeController(controller);
controller.CallMyInitialize();
//TODO: verification of MyInitialize assumptions
}
Is that clear?

Using castle windsor with interceptors and asp.net

I'm trying to add logging with aspect orientated programming using castle windsor in plain asp.net, i.e. not MVC
I've added a class that implements the IInterceptor interface and an attribute that inherits from Attribute.
public class LogAttribute : Attribute
{
public Level LogLevel { get; set; }
public LogAttribute(Level level)
{
LogLevel = level;
}
}
public class LoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
MethodInfo mi = invocation.Method;
LogAttribute[] atts = (LogAttribute[])mi.GetCustomAttributes(typeof(LogAttribute), true);
// if method not marked with InternalUseRestricted attribute, then pass on call
if (atts.Length == 0)
{
invocation.Proceed();
}
else
{
ISeiLogger log = LoggerFactory.GetLogger(mi.DeclaringType.ToString());
//assume only one logging attribute
//log on entry
log.LogEnter(atts[0].LogLevel);
//allow code to continue
invocation.Proceed();
//log on exit
log.LogExit(atts[0].LogLevel);
}
}
}
Now in the global.asax.cs I've added the following:
public partial class Global : System.Web.HttpApplication, IoCProvider
{
private void InitializeIoC()
{
container = new WindsorContainer();
container.Install(new Sei.Aspect.AspectInstaller());
}
public IWindsorContainer Container
{
get { return container; }
}
private static Sei.Logging.ISeiLogger log;
private IWindsorContainer container;
public override void Init()
{
base.Init();
InitializeIoC();
}
and I've created an installer class:
public class AspectInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
//container.Register(AllTypes.FromAssembly(Assembly.GetExecutingAssembly()).BasedOn<IInterceptor>().Configure(component => component.LifeStyle.PerWebRequest));
container.Register(Component.For<IInterceptor>().ImplementedBy<LoggingInterceptor>().LifeStyle.PerWebRequest);
container.Register(Component.For<IInterceptor>().ImplementedBy<InternalUseRestrictedInterceptor>().LifeStyle.PerWebRequest);
container.Register(Component.For<IInterceptor>().ImplementedBy<CachingInterceptor>().LifeStyle.PerWebRequest);
}
}
I now want to add the attribute to some arbitary page's code behind class and some arbitary virtual method, as in
[Log(Level.Info)]
protected string Login(string username, string password)
{
DoSomething();
}
This obviously doesn't work. Do I need to change the way I'm instantiating the page (its a page's code-behind class) to use a container? Or is it the way I'm registering the interceptors? I want to be able to use the interceptors on any class going forward and not have to tell the container about each and every class that I have in my application.
Short answer: it's not possible.
Long answer: due to the way ASP.NET Web Forms works, it doesn't let anyone interfere with the page instantiation. Some claim that using a custom PageHandlerFactory lets you do IoC, but this only lets you set properties after the page has been instantiated, which is simply not enough for proxying.
So runtime proxy libraries such as DynamicProxy or LinFu can't do anything about this. But you may be able to use compile-time aspect weavers, such as PostSharp.
Alternatively, make your code-behind as slim as possible, deferring actual logic to Windsor-managed components.

Resources