Showing posts with label static. Show all posts
Showing posts with label static. Show all posts

Wednesday, March 28, 2012

PageMethod problem

HI. I have a problem with calling static PageMethod in asp.net ajax.

Problem apperars then i use UrlMappings. For example i have this code in web.config

<urlMappings>
<add url="~/ComputerManager/WorkstationList.aspx" mappedUrl="~/ComputerManager/ComputerList.aspx?comp_type=1"/>
<add url="~/ComputerManager/ServerList.aspx" mappedUrl="~/ComputerManager/ComputerList.aspx?comp_type=2"/>
</urlMappings>
and this code in ComputerList.aspx. cs
[WebMethod]
public static string SetSelection(string ID,string dataKey,bool state)
{
...
}

so, when call PageMethods.SetSelection(...) a have a error "The server method SetSelection is failed".

post url ends with WorkstationList.aspx/SetSelection

any ideas?

Hi,

You are rewriting your URL, and these URL are fixed one. They don't cater for any extra items or query string parameters. Thats why they don't map to actual page when you want to do that. In this case I will recommend that you add another entry with following items

<urlMappings><add url="~/ComputerManager/WorkstationList.aspx" mappedUrl="~/ComputerManager/ComputerList.aspx?comp_type=1"/><add url="~/ComputerManager/ServerList.aspx" mappedUrl="~/ComputerManager/ComputerList.aspx?comp_type=2"/><add url="~/ComputerManager/WorkstationList.aspx/SetSelection" mappedUrl="~/ComputerManager/ComputerList.aspx?comp_type=1"/><add url="~/ComputerManager/ServerList.aspx/SetSelection" mappedUrl="~/ComputerManager/ComputerList.aspx?comp_type=2"/></urlMappings>

Then i use mappings like you suggested, i get a request to pageComputerList.aspx with parametercomp_type=1, insted of calling PageMethod.

So i rewrite it this way

<urlMappings>
<add url="~/ComputerManager/WorkstationList.aspx" mappedUrl="~/ComputerManager/ComputerList.aspx?comp_type=1"/>
<add url="~/ComputerManager/ServerList.aspx" mappedUrl="~/ComputerManager/ComputerList.aspx?comp_type=2"/>
<add url="~/ComputerManager/WorkstationList.aspx/SetSelection" mappedUrl="~/ComputerManager/ComputerList.aspx/SetSelection"/>
<add url="~/ComputerManager/ServerList.aspx/SetSelection" mappedUrl="~/ComputerManager/ComputerList.aspx/SetSelection"/>
</urlMappings>

and that solves my problem.

Thanks for good idea,ziqbalbh.

PageMethods (which are static) and access Session from them ?

Since PageMethods are static if I need the access to the Session how should I go about it ?.

One straightforward way may be to add a field in my (Page) class like this

public partialclass MyPage : Page {private static MyPage _p;protected void Page_Load(object sender, EventArgs e){ _p =this; } [ScriptMethod][WebMethod]public static void MyPageMethod(string contextKey){int a = (int)_p.Request.Session["myintval"]; } }
Do you guys thinking this is the only and best way to do it ?.
Please suggest.

Regards & thanks

Kapil

you could do it in more simple way:

instead of

int a = (int)_p.Request.Session["myintval"];

int a = (int) HttpContext.Current.Session["myintval"];

The static property Current of HttpContext is accessible from everywhere.

Cheers,

Yani


An even better solution would be to implement a facade pattern for your session (more infohere).

Regardless of anything else you do in terms of code style and whatnot, you have to change your WebMethodAttribute to

[WebMethod(EnableSession=true)]


silly me, huh. I knew I was doing something wrong.

Thanks for the answer Yani

Regards

Kapil

PageMethod Static Ajax WebService and User Controls

I have a page HostPage.aspx, which is a generic hostpage that will dynamically load Web User Controls at runtime, according to the needs of various other users. Those other Web User Controls will be created by the other users, such that they can put anything they like in that Web User Control, and it will be dynamically populated and put in the HostPage.aspx. They will always use HostPage.aspx, they cannot edit it. This is working as-is, and everything is great.

Now, some users want to put AJAX functionality in their User Controls, such that the HostPage.aspx will contain their User Control, the User Control will contain an UpdatePanel, a ScriptManager, etc.

To enable page methods, we have to set the EnablePageMethods="true" on the scriptmanager, and have to declare a static method *somewhere*. The requirements are such that we cannot be declaring these static methods in the HostPage.aspx, because it cannot know what the controls, and therefore static methods, are until runtime. On the other hand, if we declare these static methods in the User Control, it's not defined in the HostPage, and AJAX PageMethod callbacks fail ("Method myMethod is not defined"), because the page doesn't know of it's existence.

1. Has anyone tried to do something similar to this, namely having AJAX controls in a User Control, which is hosted in a page, yet also needs to use the Page Methods, yet cannot declare them in the page (I know, that's pretty specific).

2. Any ideas on how this might be accomplished?

I'm thinking of using Reflection or DynamicMethod (http://msdn2.microsoft.com/en-us/library/system.reflection.emit.dynamicmethod.aspx) to make this happen, such that at runtime, the page will examine its child controls for any static methods with the ScriptService attribute, and then dynamically create a static method on itself with the same name, calling the child, but that is rather involved and I fear the performance risk of this (if this whole idea is even possible). Plus, the generated method wouldn't exist until after the controls exist, and I'm not sure where that falls in relation to the timing of the AJAX extensions (looking for the MethodName). It might be (probable) that the handler is looking for the method even before the controls are initialized, in which case that idea won't fly.

You can't do that... as described here (http://www.singingeels.com/Articles/Using_Page_Methods_in_ASPNET_AJAX.aspx) Page Methods are only on pages :)

But you can get what you want if you make your user control register a "web service" as in this article:http://www.singingeels.com/Articles/Consuming_Web_Services_With_ASPNET_AJAX.aspx

If your users aren't able to add webserivces (I really don't know the situation your building)... then they can register a regular old "AsyncPostBack" and wire it up themselves (sorry, no article on that yet).


Right, I understand completely the concept of PageMethods, that they are on pages, etc. That's why this is a bit of a tricky spot.

I guess what I'm looking for is whether anyone has come up with anything clever to get around this situation (PageMethods from a Usercontrol). The usersare free to create and consume their own webservices, if they like, but if possible, I would like to give them this functionality for this situation.


OK, I believe it's Page.ClientScript.RegisterAsyncPostBack or maybe ScriptManager.RegisterAsycnPostBack ( I can't remember )... either way, it'll post back to the page... and ultimately the user control, and fire an event (on the user control).

That'll work just like the page methods... (a little better actually for what you're doing)

Monday, March 26, 2012

PageMethods static, ASMX and security

Hi,

I just tried out the PageMethods approach and at first, i got this weird "PageMethods not defined", then I found out that's because my codebhind method needs to be static. Why is that? Should I use asmx instead cuz i just feel weird to declare static methods everywhere in my codebehind.

If i use asmx for my ajax methods.. what if people start to hit my asmx directly outside of my website? I want to prevent ppl from directly accessing my webmethods. (I'm not that good with webservcies, but my understanding it of it is any .asmx page is accessible to the public?)

Please give me some of your insight into this matter. Thanks a lot.

Hi,

I'm not sure about what I'm going to say but it seems you can use Sessions to verify that a user is authenticated on your web site. By adding the EnableSession attribute to a WebMethod, you can access all the session data like in a normal aspx page. I tried that with an AutoCompleteExtender and a WebMethod, and the WebMethod doesn't return anything if the user isn't authenticated.

Hope this helps.

Laurent


Hi Laurent,

That's some good information. Do you know how can I enable the default membership authentication with it? like some types of attribute [authenticated=true] type of things?
Thanks a lot. That clears up some of my confusion.

There's no attribute for that that I'm aware of, but doing something like:

[WebMethod(EnableSession=true)]
public string HandsOffMyStuff()
{
if(!User.IsAuthenticated)
throw new Exception("hands off, jerky!");

/// Do cool stuff
}

will solve your issue for you.


Ah, coolbeans. thanks a lot. Strange that this wasn't documented anywhere, i'd imagine by NOT doing this, most of the ajax implementation are exposing themselves unnecessarily. Security aside, your bandwidth is exposed for usage. hm..

I just read by decorating <scriptservice> attribute will solve security issue, but I wasn't sure what they are talking about exactly. I'll have to test it out quickly.

Here is a blog talking about it.

http://portal.spidynamics.com/blogs/developersecurity/archive/2006/10/31/Web-service-security-improvement-in-ASP.NET-AJAX-beta-1.aspx

not much explaination.

Thanks though, I'll go with User.IsAuthenticated and EnableSession check


I don't believe you need "the EnableSession=true".

This is just regular ASP.NET authentication. .asmx files, just like .aspx files or .html files, are public to the world by default unless you restrict access via authentication. That's probably why you didn't find any ASP.NET AJAX-specific documentation about this.

The blog post you pointed to was just saying that in early prerelease versions of "Atlas", all the web services in your project became accessible to script, but now you need to put a [ScriptService] attribute on the ones you want to call from script, and the rest are only callable via SOAP. This is basically an attack surface reduction.


That depends on how you're doing authentication, though. If you're doing Forms authentication, for example, you don't want to put your web services in a restricted folder, b/c the redirect to login page is not desireable behavior w/ a web service. So instead what you can do is leave it in an 'open' folder but then check authentication on the Session object as described above.


okay. just to clarify, what happens if it's a public site which allows anonymous access, and all i want to do is grant access to the asmx services from javscript calls WITHIN my own website (by decorating it with <scriptservices> attribute right? Because I don't want anybody excpet me to use my backend service.

Deos this prevents other people from referencing my web services?, u know, visual studio->add web reference? (again, I've only done limited amount of work on webservices, such asking these questions...) I'll have to do some tests to clarify all these.

Fundamentally, if you allow unauthenticated users to access your web services from the browser, you can't prevent them from doing so from some other application. Even if you disable the SOAP protocols on your web service, someone could still write their own code to use JSON to talk to your service, or even simpler, they could do a File/Save As... in the browser to download a copy of your web page and just load it in the browser (possibly changing it to call your web service 30 times a second).


hm..ic and that's what i'm worried about... espeically some of my asmx services accepts input data (write to database) like membership regirstration...(good thing that I used an email confirmation mechnism and password is generated randomly on the backend) this way, i can prevent myself from spammers.

Okay... I'll have to research some more on this before I launch my public ajax enabled website, i just need to make myself comfortable first..

Thanks a lot guys.

Okay, just to follow up on my own thread... i did a few tests.

1. calling local ajax webservices from javascript within my own website.

With [ScriptServices] attribute, my javascript is able to call the webmethods of the .asmx file. [Success]
Without [ScriptServices], it fails. [Failed]

Remote Ajax .asmx services WITHOUT forms authentication
-----------------------------
2. calling a remote ajax .asmx services from my javascript (without forms authentication) [To Test]

3. calling a remote ajax .asmx services from my codebehind (without forms authentication) [Success]

Remote Ajax .asmx services WITH forms authentication
---------------------------
4. calling a remote ajax .asmx services from my javascript (with forms authentication) [To Test]

5. calling a remote ajax .asmx services from my codebehind (with forms authentication) [Failed]

So it confirms what everyone said above. By looking at #5 and #3), my conclusion this far is, if we have forms authentication enabled, my webservices is safe. But if my site allows anonymous access, such as a public site, we need to be careful.

For example, my public site's member registration page use an ajax method to register a new member of my website. By having this ajax method available, I'm able to call the method from another site, and automatically register new members. It's dangerous because if I loop 1000 times, I'm able to create 1000 members. This is an invite for spammers. If you go through my web page, at least I can prevent spammers by using CAPCHA image or whatever, through webservices, there is no protection from direct access.

Again, it's a good thing that I created users based on email confirmation.. but still, remote direct access will leave a lot of temporary data in my database.

So now, I will remove all "Write" ajax methods from my public website, at least I can prevent useless data. But my "read" .asmx servcies methods of the public site are still all open to everyone, everybody can call my webservices whenever they want from within their own application. I can see it'll cause unnecessary bandwidth.... then again, spammer could simply hit my webpages and it'll eat up my monthly bandwidth as well. Just feel like I opened up another door for them that's all.

*headache*


Oh yeah, another way is to use PageMethods.. this looks safe from remote access, but the question remains... if i have 100 ajax methods, they are all static, twhat's the "cost" on my webserver? 100 static methods for ajax??

Hi!

I think you are a bit pessimistic on this matter. Even on a public website, you have access to a user context, which includes a session. This way, there's always a workaround, like initiating a session object in your MasterPage and looking for this object in all your webmethods. I think that would prevent from most of the possible attacks, because a malicious user would have to create a much more complex program than including a web reference.

Anyway, this same malicious user would always be able to call your web service, even if the call fail. It's like downloading an image, by default it's always possible if you know the address. If your webmethods send data which cost a lot of bandwidth, you can create a monitoring system, which will verify that a same user doesn't call your webservice more than x times a second/minute, but that would be quite heavy...

Hope this helps,

Laurent