I need to implement single page applications using ASP Web Forms. I faced with a navigation problem. I need to use a navigation pattern like this:
http:// web site url / ... / page.aspx? {query string} # {ListId} / {ItemId}
When a user request a data from the server, the request on the server doesn't contain hash # (because this is a client-side feature). And it looks like this:
http:// web site url / ... / page.aspx? {query string}
So, actually I need two requests:
to get a page without hash and load javascript;
to handle hash data using javascript and async call required data from the server.
Is it possible to implement this logic with only one request?
Are there any best practices?
You can append ListId/ItemId to query string before sending request and read it regularly on a server.
var url = 'http://example.com?param1=10¶m2=20#1000';
var beforeHash = url.split('#')[0];
var itemId= url.split('#')[1];
var processedUrl = beforeHash + '&itemId=' + itemId;
If your request is not already fired from JavaScript, you will have to hook into link's click event...
Or maybe you can get rid of # entirely and scroll content via JavaScript (my guess is that you use # because of local anchors to jump to different places in document)?
BTW There is window.location.hash property.
Update:
Based on your comment the flow is like this:
User types URL with #ItemId
Server returns the page
JavaScript reads #ItemId from window.location, puts it into QueryString and makes a request
Server returns the page based on modified QueryString
In this situation the two-requests pattern seems to be the only viable option. By design server does not get #Item part (called fragment). So there is no way to guess ItemId upon initial request. If after second (ajax) request, you refresh #ItemId dependant parts of the page through JavaScirpt, user experience will not be hindered much.
Related
When implementing the post-redirect-get pattern in a web application, it is common for the final step in your server code to look something like this (pseudocode):
if (postSuccessful)
{
redirect("/some-page?success=true")
}
That is, the redirect URL has some kind of success parameter in the query string so that you know when to display a nice looking "Your form has been submitted!" message on your page. The problem with this is that the success=true persists in the query string when it's only needed to initialize the page. If the user refreshes the page or bookmarks it, they will receive a false success message even though no additional POST has taken place.
Is there an elegant solution to this that doesn't involve using JavaScript to eliminate success=true from both the query string and the browser history? This solution works, but definitely adds complexity to a page's load process.
You can use server side technology to implement this feature, without any JavaScript. The stes are listed below:
When post is successful, redirect to /some-page with current timestamp information:
if (postSuccessful)
{
redirect("/some-page?success=true×tamp=1559859090747")
}
When server receives GET /some-page?success=true×tamp=1559859090747 request, compare the timestamp parameter with the current timestamp, check whether it is within the last 3 seconds (or you can change this number according to the network environment).
If the timestamp parameter is within last 3 seconds, then it means this GET /some-page?success=true request is a result of server redirect. If not, then it's more like a result of "user refreshes the page or bookmarks it".
In server code that handling GET /some-page, render different HTML according to the result of step 3. Display the success message only when current access is a result of server redirect.
Consider StackOverflow, where each question has a unique ID, but URLs are often overridden to include a stub in the URL. For readability and other reasons the stub helps users know they are at the right place.
I have a site that returns 200 when calling a URL like:
http://stackoverflow.com/questions/28057406/
But want the URL to update to:
http://stackoverflow.com/questions/28057406/is-it-possible-to-return-http-code-200-but-give-a-better-url-without-using-3x
The first call is technically valid and the code can retrieve the object and render it perfectly fine, but I'd like to update the URL to use the stubified one.
I'd prefer to do this without a redirect as just getting the ID causes a database call to get the object. Which would mean with a redirect the process would be:
Call http://stackoverflow.com/questions/28057406/
Retrieve item 25257999 from the database to get the name to make the stub
Redirect to http://stackoverflow.com/questions/28057406/is-it-possible-to-return-http-code-200-but-give-a-better-url-without-using-3x
New HTTP Call, so retrieve item 25257999 from the database to render the final page.
If possible I'd like to not use Javascript either.
So, is it possible to return Location as part of a HTTP header with a status code of 200 and the actual page, or am I stuck using 3xx calls or Javascript?
If you are just doing HTTP, you can either choose to redirect, or not choose to redirect... You can also (with Content-Location) tell the client that the canonical address is actually somewhere else... but no browser will respond to that.
To avoid the database-call, you could of course just cache the result.
If you are in a browser however, you can dynamically update the current address without forcing a refresh, with window.history.pushState.
For more information about that call, see this other SO answer:
Modify the URL without reloading the page
Im using Visual Studio 2012 and creating a web page using "ASP.NET Web Site (Razor v2)"
Im using Java to generate a random link;
<script>
var random = new Array();
random[0] = "example1.com";
random[1] = "pattern1.com";
random[2] = "specimen1.com";
</script>
<script>
function randomlink() {
window.location = random[Math.floor(Math.random() * random.length)];
}
</script>
A Random URL
When I click the A Random URL link it opens a random page from the list in the script above. I'ts all good, but because its a verry big list I need a way to do the same without having it in HTML because its slowing the loading of the page since its in the _SiteLayout.cshtml. Thanks.
Among your choices are the following options:
Send all the URLs to the client and have the client pick a random choice.
Have the server pre-pick the random URL and send only that one to the client (it can just be put directly into the <a> link. No need for javascript at all.
Make an ajax call to the server to request a random link and when that is returned, go to it.
Make a get request to the server and have the server return a redirect to a randomly chosen URL.
It sounds like you don't want to implement the first option if you have a zillion URLs.
The second option is probably the easiest as it requires only slightly modifying the generation of the page and requires no new server APIs. You just have to figure out how to select a random URL in your server-side environment.
The third and fourth options are the least efficient as they require a call to the server, a response from the server with the new URL and then a client redirect to the actual URL.
I would pass the random url with the page when it renders from the server. You can generate the url on the server using c#'s Random class.
A Random URL
Just pass a model that you reference in your view.
I'm trying to post the entire asp.net form to a certain url.
I have tried:
$.post("http://www.someaddress.com", $("form").serialize());
I have also tried:
$.ajax({
type:"POST",
url:"http://www.someaddress.com",
data: $('form').serialize(),
success: function(){
alert('yay');
}
});
In both cases the submit is fine but no data is passed along with it.
When i test the form.serialize() in firebug console, this shows my form serialized just fine. When i view the submit in fiddler, i can see that the data part is not set. Maybe im not understanding the data part, but every single tutorial shows this as the way to go -> serialize the form and set that as data. What must i do to get my serialized form as the data in my request?
What am i missing? Also - why does the NET tab in firebug show all these requests as method OPTIONS?
is this
url:"http://www.someaddress.com"
just an example or do you try to access a foreign domain? (which would explain the problem).
Based on your comment, the ajax same origin policy does not allow to access a foreign domain.
You cannot do a Ajax request to a foreign domain. As this is not allowed (against security) in javascript to access a foreign page ( not on your domain )
I read some values from text boxes and send them via jQuerys post method to an server. If the user enters text containing something like "bla bla", the call fails. The data looks like this in that case:
var data = { myKey: 'bla <script> bla' };
And I send it to the server like this:
$.post(targetUrl, data, function(x) {...});
On the server side (an Asp.Net web form) it looks like the call never reaches the server. Any hint how to solve that? If there's a convenient function which cleans data from bad tags, that would be fine too.
Have you desactivate the validate request of your aspx page?
add this in your page declaration: validateRequest="false"
To strip tags using a jQuery function:
jQuery.fn.stripTags = function() {
return this.replaceWith( this.html().replace(/<\/?[^>]+>/gi, '') );
};
Do you receive a page_load in ASP.NET? If yes, isn't there anything in Request.Params?
I would suggest escaping your values client side using the javascript escape function as shown below
var data = { myKey: escape('bla <script> bla') };
Once you have done that, you can retrieve the correct value on the server side using the following (.Net Code)
HttpUtility.UrlDecode(param_value_to_decode)
I tested this and the correct value is being passed correctly to the server via the post request.
Hope this helps.
Additional Info : I forgot to mention the cause of the error. When inspecting the request using firebug, it returns a "500 Internal Server Error - A potentially dangerous Request.Form value was detected from...". This is a built in protection mechanism from asp.net to protect against script injection. The following page directive ValidateRequest="false" did not solve the problem as expected (Works in traditional WebForms). It might be something specific to the Mvc platform, not to sure. The above solution does work, so just use that.
Regards
G