Is there away to get the current fragment from a route that was issued via action link. This is how I am getting the action from the route.
string currentAction = requestContext.RouteData.Values["action"] as string ?? "index";
Can I do something similar to this?
string currentFragment = requestContext.RouteData.Values["Fragment"] as string ?? "";
No, you can't do anything like this. The fragment (everything that follows the # sign in an url) is never sent to the server by the browser, so the sole fact of talking about getting the url fragment server side simply doesn't make sense.
So if you have the following url: http://example.com/foo/bar?key1=value1#abc the server will never be able to fetch abc simply because the client will never send it.
As it has already been pointed out that is not possible. Document fragments (the string after the hash as you call it) are intended for the browsers only to correctly position the viewport. They have no meaning for the server and therefore are not transmitted there.
There is however a workaround you can use. Repeat the fragment as part of your url to make it accessible for the server.
Look at the permalink to the answers in this question. For instance, the link to my answer looks like this:
http://stackoverflow.com/questions
/6285833/get-current-fragment-in-route-asp-net-mvc/6286097#6286097
See how the value 6286097 is duplicated as the last route parameter. It's intentional. You can use this technique as well.
P.S. The fragment must point to an identifier in the document (id of some HTML element). At least in XHTML only identifiers work as fragments. Valid ids may not begin with a digit therefore instead of #6286097 use something like #answer-6286097.
P.S.#2. Do not use any JavaScript trickery to get around this limitation. Basic site functionality and design must work without JavaScript - don't listen to anyone who tells you otherwise. Fragments obviously belong to the basic tool box. Use JavaScript only for advanced interactivity.
I have a workaround for you, but first of all lets get more into the problem.
The strings after the hash symbol which are called Fragment values are not query parameters but they are strings to be read by the client-side (living in the browser) and the server cannot read them because they are not sent to the server by the browser.
Some authentication providers like Google and Azure send the access token as Fragment value for security reasons so that they are not transferred over the internet after they get sent as direct response from the authentication provider.
The only way you can come around that is to use javascript to convert the fragment values to query parameters by replacing the '#' with '?' and redirecting to the endpoint in your server controller.
I suppose the easiest way is to handle all that from server, meaning you get get the request in server, send a javascript code to the browser on the fly, that replaces the '#' into '?' and redirects to your second endpoint which reads the token as strong parameter.
Here how you can do it in ASP.NET Core 3.1:
[AllowAnonymous]
[HttpGet("authredirect")]
[Produces("text/html")]
public virtual ContentResult ConvertUrlFragmentToQueryParamThenRedirect()
{
return Content("<html><script>window.location.href=window.location.href.replace('#', '?').replace('authredirect', 'authparams')</script></html>", "text/html");
}
[AllowAnonymous]
[HttpGet("authparams")]
public virtual void GetAccessToken([FromQuery] string access_token)
{
// now you have your access token server side here
}
Please remember to set your redirectUrl to the correct one, in this case 'YOUR REDIRECT URL/authredirect'.
Related
How do I clear/remove query string parameters, which my MVC action, doesn't require/support?
For instance, my action requires, say an id and a bool flag, so the url would be something like: http://localhost:someport/controller/action/?id=1&remove=true
But, if a user types in something like, http://localhost:someport/controller/action/?id=1&remove=true&some-junk-param=0
Then, I want the some-junk-param to be removed and not shown in the address bar, when the request is processed.
Any thoughts?
If you need to get rid of unwanted query string parameters, you have two general options:
Do it on server-side. You can achive this only with redirection, that means when browser asks URL with bad query string, server redirects browser to URL with good query string.
Caveats:
In this case we have redundant query just for cleaning query string.
User will have trash in browser history.
Do it on client-side. ASP.NET MVC Model binder will get only expected parameters from query string, so it's nothing bad with having other values in query string. You can check your URL on client-side with javascript and rewrite it with or without changing history using History API (IE10+).
Caveats:
In this case you will have to support consistency about allowed parameters between JS and C# code
Of course every way is suitable for it's own cases, but looking at caveats the second way is better, because it affects developer expirience whereas first way affects user expirience.
I'm using a Bank E-Payment webservice and set the redirectURL into http://Example.com/EPaymentResultCallback?Param1=0&Param2=1
when the bank finish it's job, browser redirects to preceding url.
But the problem is: Bank webservice has changed my url into http://Example.com/EPaymentResultCallback?Param1=0&Param2=1 (noticing the extra &).
In fact my innocent url encoded and therefore Param2 will be lost.
I cannot change the websercive obviously. but interested to know if there is a way to resolve the second url parameter (Param2) on my website?
For more general explanation: 'mywebsite' calls a webservice and redirected to a whole new website. after 'new website' done, browser redirects to the given URL (in fact 'mywebsite/somesubUrl/param1¶m2') but parameter separator (&) changed into (&) so the second parameter (param2) won't delivered correctly to the action method and an exception raise, pointing that the second input parameter in the action method could not be null.
Actually i`m looking for a built-in solution to read encrypted url. that would be the best. but any other idea is welcomed.
I am working on an application with ASP.NET MVC Routing + AngularJS routing.
My URL lookslike:
https://example.com/Request/#/Search/Request/123
when I breakdown this (http://example.com/Request) is handled by ASP.NET MVC routing. i.e. (Area = Request, controller = "Default", action = "Index")
(#/Search/Request/123) is handled by AngularJS routing.
This works perfectly when I am on http://localhost:8080/
The issue is when I deploy this application to https://example.com/
In this case, If user clicks on above link (received via email),IE 9 recognizes only (https://example.com/Request/") and the server never gets (#/Search/Request/123).
We have enterprise SSO implemented on web server. SSO client intercepts http request and uses URL to redirect back to requested page after authentication.
if # fragment is not sent as part of http request url, sso is not able to redirect back to same page.
I believe this to be a common scenario/issue. I would keep changing the URL scheme as last resort. e.g. (# to !).
How to solve this?
Just found a blog that dealt with this issue exactly:
http://codetunnel.io/how-to-persist-url-hash-fragments-across-a-login-redirect/
He offers two ideas:
When the page loads there simply needs to be some JavaScript that accesses the hash fragment and appends it to the redirect URL in the hidden field. Here's an example using JQuery for simplicity
$(function () {
var $redirect = $('[name="redirect"]');
$redirect.val($redirect.val() + window.location.hash);
});
Or, alternatively
Instead of appending the hash fragment to the hidden field value, you could avoid sending it to the server at all and simply append it to the form action URL.
$(function () {
var $loginForm = $('#loginForm');
var actionUrl = $loginForm.attr('action');
$loginForm.attr('action', actionUrl + window.location.hash);
});
Fragments (the part of the URL after the #) are not necessarily sent to the server-side by the browser. They are for client-side usage only (navigating to a specific location in the document, JavaScript support).
RFC 2396 section 4.1:
When a URI reference is used to perform a retrieval action on the
identified resource, the optional fragment identifier, separated from
the URI by a crosshatch ("#") character, consists of additional
reference information to be interpreted by the user agent after the
retrieval action has been successfully completed. As such, it is not
part of a URI, but is often used in conjunction with a URI.
(emphasis added)
Therefore, the URL scheme you came up with will not work reliably unless you change the # to another character. Alternatively, you could use JavaScript to transfer the information from the fragment in an input that will be reliably passed back to the server. But do note that solution will only work if JavaScript is enabled in the browser, so it is (also) not a 100% reliable solution that will work with all clients.
Either way, using a URL without a fragment is a more reliable approach and IMO a better design choice if you expect that part to be interpreted by the server.
I would remove ugly URL's from your application all together.
This article will walk you through removing ugly URL's in a asp.net-mvc project. It will also ensure that you have your RouteConfig.cs setup correctly.
http://www.codeproject.com/Articles/806500/Getting-started-with-AngularJS-and-ASP-NET-MVC-P
I am working on an application that uses Angular.js and ASP.NET MVC. The routes for angular.js contain a '#'. Some pages in the application can be viewed without needing to log in. These pages however contain URL's to pages in the application that need the user to be logged in. They look like:
Want this voucher?
So when these links are clicked, MVC forms authentication redirects to the sign in page with the return URL query string that looks like this:
http://localhost:18030/signin?ReturnUrl=%2f#/shop/voucher/6bc1
So on the sign in pages, when i try to look at the query string I only get '/' for return URL as that is the %2f part. I lose the remaining value because of the #.
If I try to URL encode the link, the # and other '/' characters do get encoded but then the routing gets messed up and I get 404 errors.
Is there anyway to access the full query string value with the '#' in it? I am not sure why forms authentication does not encode the #.
The url fragment is never sent to the server, so you have to get a little creative here.
One way I have solved this in the past is to use client side code to modify the action URL for the login, and append the fragment as a query string parameter.
//Pulls out everything past the '#'
var fragment = $location.path();
$scope.fragmentParam = "&fragment=" + fragment;
You can append that query string param to your form action, and then handle it on the server side in order to redirect the user appropriately.
public ActionResult Login(MyLoginInfo info, string returnUrl, string fragment){
//Normal login code
var redirectUrl = String.Format("{0}#{1}", returnUrl, fragment);
Redirect(redirectUrl);
}
This is a simplified version, but you should be able to get the general idea. You need to pass that information to the server, and then reconstruct a redirect url that includes the fragment.
I'm considering using the hash method to create static urls to content that is managed by ajax calls in a Asp.Net MVC. The proof of concept i'm working on is a profile page /user/profile where one can browse and edit different sections. You could always ask for the following url /user/profile#password to access directly to you profile page, in the change password section
However, i'm wondering if i'm not starting this the bad way, since apparently i can't access the part after the hash in any way, except by declaring a route value for the hash in global.asax. So i'm wondering if this is the right way to access this part of the url?
Am i supposed to declare a route value, or is there another way to work with hash values (a framework, javascript or mvc)?
Edited to add:
In pure javascript, i have no problem using the window.location.hash property, i'm not sure though how standard it is in today's browsers, hence the question about a javascript framework/plugin that would use it.
The thing is that the part that follows the hash (#) is never sent to the server into the HTTP request so the server has absolutely no way of reading it. So no need to waste time in searching for something that doesn't exist.
You could on the other hand tune your routes to generate links that contain the hash part so that client scripts can read it.
Send the hash value document.location.hash as a parameter to the controller action of your choice.
This can be done in the code if needed...
RedirectResult(Url.Action("profile") + "#password");
should work fine