2

I'm trying to pass ReturnUrl query string to my login page. I have a partial Login view (kind of like a login box) and a login view. Right now, I have the following line in my partial view:

using (Html.BeginForm("Login"
                    , "Account"
                    , new { returnUrl=HttpUtility.UrlEncode(
                                      Request.QueryString["ReturnUrl"]) 
                                      ?? HttpUtility.UrlEncode(Request.Path)
                           }
                    , FormMethod.Post))

When I click on my partial view's submit button(e.g. from http://localhost:12345/Product/1234/Product1),

I'll get redirected to my login page with the following url:

http://localhost:12345/Account/Login?returnUrl=%2FProduct%2F1234%2FProduct1  

But if I log on, I'll see an http 400 response, because the page is returning to

http://localhost:12345/Account/%2fProduct%2f1234%2fproduct1.

Also, if I type in the wrong credentials, I cause the returnUrl query string to be encoded again thus every % character is converted to %25 again!

I should mention if I manually type in

http://localhost:12345/Account/Login?returnUrl=/Product/1234/Product1

(without encoding) and log in, I'm successfully redirected to the specified path.

I guess I'm missing something obvious. But couldn't find out what.

Thanks.

1
  • 1
    isnt the encoding done automatically for you? you don't need to encode it yourself. Commented Dec 31, 2011 at 18:38

2 Answers 2

3

You don't need to encode it when you pass it to Html.BeginForm() Just use the value without encoding it as it is encoded by the TagBuilder when assigning the value to the action attribute of the generated <form> element

@using(Html.BeginForm(
    "Login", 
    "Account", 
    new { returnUrl= Request.QueryString["ReturnUrl"] }, 
    FormMethod.Post)) {

    @* form here *@    
}

I've removed the null-coalescing operator and Request.Path too because if ReturnUrl is null, it's not going to matter to the generated url assigned to the action attribute (assuming it's an optional parameter in your routing, or an optional property on your ViewModel).

The relevant source code in TagBuilder is (comment mine)

private void AppendAttributes(StringBuilder sb) {
    foreach (var attribute in Attributes) { 
        string key = attribute.Key;
        if (String.Equals(key, "id", StringComparison.Ordinal /* case-sensitive */) && String.IsNullOrEmpty(attribute.Value)) { 
            continue; // DevDiv Bugs #227595: don't output empty IDs 
        }

        // ---------------------------------------
        // Value will be HTML attribute encoded by 
        // the Encoder set for the application
        // ---------------------------------------
        string value = HttpUtility.HtmlAttributeEncode(attribute.Value); 
        sb.Append(' ')
          .Append(key)
          .Append("=\"")
          .Append(value) 
          .Append('"');
    } 
}
Sign up to request clarification or add additional context in comments.

Comments

2

You may want to use this to avoid encoding of your return Url:

@Html.Raw([Your Return Url])

Hope this helps!

Matt

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.