While developing my app (asp.net mvc3) locally everything was fine using the VS dev app server. The app was located at localhost/. However, I'm attempting to deploy the application on a IIS 7.5 server in a /Management directory and having a lot of routing issues as a few calls in my app rely on the app being at the route.
I have some javascript code that calls my controller through an ajax call that looks like this:
url: "/en/Home/GetFormula/"
I would like it to go to: /Management/en/Home/GetFormula but instead it's going to the root of the site and looking for /en/Home/GetFormula and returning 404 errors.
Any ideas on how I can fix my javascript routing to default /Management/ as the root of the site?
Thanks
When the pseudo-URL passed to an HTTP request begins with a slash (e.g. "/path/to/resource"), the pseudo-URL is "completed" by treating it as if the given path were under the Web site's root directory (e.g. "http://my.site/path/to/directory").
Clearly, you were expecting the pseudo-URL to be processed as if the given path were under your Web application's root directory. Well, I have bad news for you: The HTTP protocol does not deal with such a thing as a "Web application".
The ASP.NET MVC Framework provides the Url.Content function, which takes pseudo-URLs beginning with a tilde character (e.g., "~/path/to/resource") and returns the result of replacing the tilde character with the Web application's root directory (e.g., "http://my.site/an/application/path/to/resource", assuming the Web application's root directory is "http:/my.site/an/application"). However, the ASP.NET MVC Framework is only available on the server side. If your JavaScript runs on the client side, it cannot call Url.Content.
But not all is lost. The ASP.NET MVC Framework allows you to dynamically generate JavaScript code on the server and run it on the client, the same way it allows you to dynamically generate HTML content and of course send it to the client. That way, you can expand the pseudo-URLs into actual URLs on the server side, and deploy the resulting JavaScript code to the client.
To avoid confusion about where you are currently try:
url: document.URL + "/Management/Home/GetFormula"
I solved this issue adding a html hidden field on my page where, on the server side, I put the correct url inferred with the Url.RouteUrl method like this:
<input id="MyHiddenFieldName" name="MyHiddenFieldName" type="hidden" value="#Url.RouteUrl(new { area = "MyArea", controller = "MyController", action = "MyAction" />
then, on your javascript code you could do this:
url: $("#MyHiddenFieldName).val()
Related
I am working on an application which loads multiple js files on client side during first hit in browser. It takes quiet a bit of time to load the first page of our application which can be improved using server side rendering.
We are using java and spring in our backend application. So I am looking for a way to load all the js files on server side during application load(server startup) instead of client side. So I removed js file reference from the jsp and I am trying to load the js files using nashorn as below:
#Configuration
public class ConfigureScript {
#Bean
ScriptTemplateConfigurer configurer() {
ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
configurer.setEngineName("nashorn");
configurer.setScripts("/js/common/common.js", "/js/utils/utils.js");
configurer.setRenderFunction("render");
configurer.setSharedEngine(false);
return configurer;
}
}
But somehow this doesn't seems to work for me since application just keeps loading. Can you guys please suggest the problem with above code or some other way to achieve the server side loading of js files?
Also, if you can suggest is there a way to debug whether js files are loaded properly or not?
for debugging I use postman chrome plugin. When server side rendering takes place - hit to the basic url (e.g. "/" or any other supposed) returns the content rather than jsp template.
removing js files from jsp - not sure this is correct. js should handle anyway some users interactions in browser after the rendering on server side, except probably that would be fine if content returned from server is static.
in snipped above - two files are loaded. the way how nashorn works - it builds the entire hierarchy of js objects, required for rendering. Are those files enough? Implementation of "render" function should take the job to render.
Is it possible to serve a dynamic html page without a backend server or without using a front-end framework like Angular?
Edit
To clarify, the index file is served from a backend. This question is about how to handling routing between the index and dynamic pages.
I have an application that consists of two files - index.html and dynamic.html. When the user clicks an option say "Option A", they are served dynamic.html and the url is updated to /option-a. Now, with a server this is no problem and assuming the user visits the app from the landing page, it isn't a problem either because a cookie can be set. However, suppose a user visits a page at my-domain/option-a. That route doesn't exist and there is no server to redirect so it will 404. They would have to visit dynamic.html.
I think this architecture demands that there's either a server to handle route redirects or a SPA framework.
Is there something I'm missing?
your SPA framework will be active only once your HTML page is loaded and to do that you need to redirect any URL that user tries for your domain to that HTML file. For this you obviously need a server (and since you are talking about my-domain/option-a I assume you have atleast a basic server). You can refer to this link to get an idea on how server can redirect a URL to specific html file: Nodejs - Redirect url.
Once HTML is loaded you can initialize your SPA framework and decide the template to be loaded based on the URL.
Note: without a server you will access URLs using file://somepath/index.html and anything other than this URL will result in 404 and no SPA framework can handle that.
I think the solution is to use a static site generator such as Jekyll or Middleman and allows you to convert information into static pages. That way you functionally are building a bunch of pages but they are all compiled ahead of time. You can add dynamic content that is loaded in from a yaml file and it will compile the content into separate html pages.
It is not possible, but there is a workaround using url parameters like this:
my-folder/index.html
my-folder/index.html?=about
my-folder/index.html?=about/sublevel
my-folder/index.html?=profile
my-folder/index.html?=./games
const urlParams = new URLSearchParams(location.search);
const route = urlParams.get('');
console.log(route);
// Should print "about" "about/sublevel" "profile" "./games"
Of course this approach is not as clean as using a server for routing, but it's the best you can get without a server.
BTW. I tried an alternative solution creating symlinks with all the target routes pointing to the same index.htmlfile. But it did not work because the browser (firefox) redirects by default when it finds a symlink, thus home is shown all the time.
I just removed # tag from my url of angular single page app.
I did like.
$locationProvider.html5Mode(true);
And It worked fine.
My problem is when I directly enter any url to the browser it showing a 404 error. And its working fine when I traverse throughout the app through links.
Eg: www.example.com/search
www.example.com/search_result
www.example.com/project_detail?pid=19
All these url's are working fine. But when I directly enter any of the above url's into my browser it showing a 404 error.
Please any thoughts on it.
Thanks in advance.
Well i had a similar problem. The server side implementation included Spring in my case.
Routing on client side ensures that all the url changes are resolved on the client side. However, When you directly enter any such url in the browser, the browser actually goes to the server for retrieving a web page corresponding to the url.
Now in your case, since these are VIRTUAL urls, that are meaningful on the client side, the server throws 404.
You can capture page not found exception at your server side
implementation, and redirect to the default page [route] in your app.
In Spring, we do have handlers for page not found exceptions, so i
guess they'll be available for your server side implementation too.
When using the History API you are saying:
"Here is a new URL. The other JavaScript I have just run has transformed the page into the page you would have got by visiting that URL."
This requires that you write server side code that will build the page in that state for the other URLs. This isn't a trivial thing to do and will usually require a significant amount of work.
However, in exchange for that work you get robustness and performance. When one of those URLs is visited it will:
work even if the JS fails for any reason (such as a dropped network connection or a client (such as a search engine) that doesn't support JS)
load faster than loading the homepage and then transforming it with JS
You need to use rewrite rules. Angular is an single page app, so all your request should go to the same file(index.html). You could do this by creating an .htaccess.
Assuming your main page is index.html.
Something like this (not tested):
RewriteRule ^(.)*$ / [L,QSA]
L flag means that if the rule matches, don't execute the next RewriteRule.
QSA means that the URL query parameters are also passed with the rewrited url.
More info about htaccess: http://httpd.apache.org/docs/2.2/howto/htaccess.html
I have a localhost with a few projects, so this project in VS2010 properties->web->use local IIS web server = 'localhost/project4/'. (I can't use the normal debug VS Development Server as some components won't work in my project) Anyhow, localhost is fine no big deal, so I go on coding.
Now, in ajax when I call .load('/Account/LogOn'); it gives me 'localhost/Account/LogOn' but what I really want is 'localhost/project4/Account/LogOn' because it is sitting in the project4 directory, not the root.
Any idea how to tell ajax I need that virtual directory prefix between domain name and the rest of the url?
EDIT --------------------------------------------
Thanks guys, combined with all your knowledge, I guess the best ways to do it are:
Include the js script into .cshtml server side and use "~/Account/LogOn/" let .net figure out the path.
Make a global var remove_me_debug_only_virtual_directory = "/project4/"; in js code. append it to the domain name. this way we don't have to pull .net into the water and write js code in .cshtml.
Move the project to localhost/ root if you can, in this case I can't, because other people at work wants to access this networked server and do demo.
If your JS code is in an MVC cshtml file, use it like this:
.load('#Url.Action("LogOn", "Account")');
The proper URL will be placed in the concrete JS code.
According to .net documents,
Absolute and relative path references in a server control have the following disadvantages:
Absolute paths are not portable between applications. If you move the application that the absolute path points to, the links will break.
Relative paths in the style of client elements can be difficult to maintain if you move resources or pages to different folders.
To overcome these disadvantages, ASP.NET includes the Web application root operator (~), which you can use when specifying a path in server controls. ASP.NET resolves the ~ operator to the root of the current application. You can use the ~ operator in conjunction with folders to specify a path that is based on the current root.
So as described above, using ~ will lead you to the root of your web project using asp:
<asp:image runat="server" id="Image1" ImageUrl="~/Images/SampleImage.jpg" />
For more information go to: Web Project Paths
Based on your update: Possible duplicate of: base url using jQuery
Where stated by #gregguida:
var l = window.location;
var base_url = l.protocol + "//" + l.host + "/" + l.pathname.split('/')[1];
//all you need to do is work with l.pathname.split('/') to find what you need.
I am a java developer but the context is same in both case,
In your can follow the steps
Check the context of your server if root is "/" then you have to call something like,
.load('/project4/Account/LogOn');
If your application is root and you can calling this request from itself then
.load('Account/LogOn');
i am a newbie on web development, so i have some problems first of all what is the meaning of ~, / on an url? My real question in my javascript code i am doing some ajax calls with jquery like that
$.ajax({
...
url: '/Membership/Login',
...
});
There is an Membership controller with an Login action method that i need to send data to. When i publish this project to IIS (my application is under xxx folder of wwwroot) i get wrong url address.
I get :
http://localhost/Membership/Login
I expect : (because my application is in xxx folder)
http://localhost/xxx/Membership/Login
Note : I dont want to add xxx to all urls.
When you use ~ in a url and call the ResolveUrl method it will put in the path to your application. You can do this in your aspx page by going:
<%=ResolveUrl("~/Membership/Login")%>
This will give you the path
/xxx/Membership/Login
which you can now give to your javascript.
Using the slash makes the url relative to the root of the web server. If you want it relative to the current url, simply remove the slash character. While the tilde character has meaning in server-side controls in ASP.NET (and UNIX paths), it has no special meaning in URLs. In the context of ASP.NET, it means to make the path relative to the application, which may or may not be the web server root. In your mark up, it should be removed, either not used by you or only used in context where it is replaced by the ASP.NET framework, such as a server-side control.
When you use the form "/some/url" you are saying take me to the root of the webserver root with that url. If you want to avoid adding "xxx" to your urls you will need to either change the web server root, create a domain name and rule in IIS for that name, or use some sort of function call to generate your urls for use.
The easiest of those three is to change the webroot on the server.