views:

242

answers:

3

This question is related to http://stackoverflow.com/questions/2185479/asp-net-forms-authentication-without-redirect only I cannot get it to work. MVC 2 changed its script files and they are now gotten as listed here:

http://www.asp.net/ajaxlibrary/CDNAjax4.ashx

Now I'm just shooting in the dark but trial and error has narrowed me down to including

MicrosoftAjax.js
MicrosoftAjaxCore.js
MicrosoftAjaxComponentModel.js
MicrosoftAjaxSerialization.js
MicrosoftAjaxNetwork.js
MicrosoftAjaxWebServices.js
MicrosoftAjaxApplicationServices.debug.js

The problem is I now get the javascript exception:

Microsoft JScript runtime error: Sys.InvalidOperationException: The path to the web service has not been set.

From googling around I've found this path should be "~/ScriptServices_AuthenticationService.asmx" but doing something like:

Sys.Services._AuthenticationService.DefaultWebServicePath = "~/ScriptServices_AuthenticationService.asmx";

doesn't work (I'm assuming it's a private member). So, the question, does anyone know how to get ajax / async FormsAuth working? Is there a definitive guide to what js file various MS ajax services depend on? Finally, if none of the above, is there a way to do FormsAuth on the server side such that it doesn't redirect (that way I can just call the controller action with an ajax form)? ... I tried using FormsAuthentication.SetAuthCookie() but that didn't seem to work for me.

Edit: I figured out that the FormsAuthentication.SetAuthCookie() is actually working but it requires the Response stream to be closed (when, of course, the buffer is sent and the cookies are set). This doesn't work for me since that's too late for my purposes.

Edit: The complete description for what I'm attempting may be necessary. The ajax form I have is for creating a new account. On the server side I create the account and login. On the front end I wait for the ajax completion event and then advance my signup wizard form to the next page that walks through other registration steps. In pseudo code, the controller action looks like:

public JsonResult CreateAsync(LoginForm form)
{
    CreateAccount(form);

    FormsAuthentication.RedirectFromLoginPage(form.Email, false);

    return Json(
        new
        {
            Email = form.Email,
            Name = form.Name,
            Message = "Success"
        });
}

The method for logging in ends the response stream and then the client-side ajax gets confused. I've tried FormsAuth.SetAuthCookie instead but has the issues as described above.

A: 

How are you rendering your form? Are you using Html.Form or Ajax.Form? If you use Ajax.Form (or even Ajax.ActionForm) you can send the login info to the controller without redirecting and decide when to redirect or not after the return of the callback in a client even. No need of a service, and the authentication state is set on server side and propagated to the client.

I have a complete code to do that if you want to try this approach. I decided not to show it right way 'cause it could be a considerable change on your architecture that you perhaps don't want to do. If you want I will post it here.

Sir Gallahad
I'm using Ajax.Form. What are you calling to do the authentication in your controller? I've done pretty much what you say but the FormsAuthentication.RedirectFromLoginPage does redirection automatically, obviously. The redirect corrupts my return response stream and the Ajax post ends up failing with a JS exception (the MS ajax scripts don't know how to parse).
xanadont
I added more clarification to the question.
xanadont
A: 

Just use jQuery to call your controller method like so.

$("#login_button").click(function(){
$.ajax({url:"/Controller/CreateAsync", data:{Email:"[email protected]", Password:"asdfasfd"}, type:"POST", dataType: "json",
success:function(data){ //do something
}) });

For documentation look here. http://api.jquery.com/jQuery.ajax/

Martin Murphy
A: 

Oh nevermind. Actually you should be using FormsAuthentication.Authenticate() instead of RedirectFromLoginPage.

You'll need to implement this behavior on your own if you'd like to call the method as a JSON request.

Martin Murphy

related questions