I have an Asp.net MVC 3 project with name of "abc". It shows http://localhost:23543/abc/.... when debugging run in VS. The url will be http://hostname/webAppName/abc/... after publish the project in a virtual folder under the default web site of IIS 7.
However, there is some jQuery ajax call, using '/scripts/...', in a separated external js file. The absolute path of '/scripts/' will become ...wwwroot/abc/scripts/... instead of ...wwwroot/webAppName/abc/scripts/.... I am creating a js function for wrapping the ajax url links.
var fullPath = '#HttpContext.Current.Request.Url.Scheme://#HttpContext.Current.Request.Url.Authority';
function GetPath(projectName, url) {
return fullPath + projectName + url;
}
In js file: ... url: GetPath('/scripts/...')....
How to get the project name? Or is there a better solution?
Use the below code to create the mvc request url
var siteRoot = '#Url.Content("~/")';
function GetPath(url) {
return siteRoot + url;
}
In your markup, you can use a site-relative URL that will be translated to the correct form at runtime:
<script type="text/javascript" src="#Url.Content("~/Scripts/myscript.js")"></script>
Usually in script what I tend to do is AJAXify existing anchor links or forms which already have the proper url as they were generated using HTML helpers.
So for example with a form (generated using Html.BeginForm helper):
$('#myform').submit(function() {
$.ajax(}
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function(result) {
}
});
return false;
});
or with an anchor (generated using Html.ActionLink helper):
$('#mylink').click(function() {
$.ajax(}
url: this.href,
type: 'POST',
success: function(result) {
}
});
return false;
});
Of course there might be some cases where you need an url other than a link or a form. What I tend to do in those cases is to use HTML5 data-* attributes on some DOM element. For example:
<div id="foo" data-url="#Url.Action("SomeAction", "SomeController")">foo bar</div>
and when I needed this url I would simply:
var url = $('#foo').data('url');
See how we don't need any GetPath function. All the urls are already part of our DOM and in the separate javascript file we simply use them.
Related
In my project i have a button that saves the changed content of an html page.
The button looks like this:
<button class="btn btn-light" title="Export (Ctrl + E)" id="save-btn" data-hmi-action="saveAjax" data-hmi-shortcut="ctrl+e">
<i class="la la-save"></i>
</button>
The saveAjax in an external file is in a couple of parts.
saveAjax: function(fileName, startTemplateUrl, callback)
{
var data = {};
data["fileName"] = (fileName && fileName != "") ? fileName : HMI.FileManager.getCurrentUrl();
data["startTemplateUrl"] = startTemplateUrl;
if (!startTemplateUrl || startTemplateUrl == null)
{
data["html"] = this.getHtml();
}
console.log(data);
$.ajax({
type: "POST",
url: 'Home/Save', //set your server side save script url
data: data,
cache: false,
success: function (data) {
if (callback) callback(data);
},
error: function (data) {
alert(data.responseText);
}
});
}
The url above is my Controller Action. When executed it gives a Error 500 on the url in the console. I have a break set in the controller and as would be expected it bypasses that.
The second part is below:
saveAjax : function () {
var url = Hmi.FileManager.getCurrentUrl();
return Hmi.Builder.saveAjax(url, null, function (data) {
$('#message-modal').modal().find(".modal-body").html("File saved at: " + data);
});
}
I have tried using a url on the razor page in the button, but since this already makes a call to the page for saveAjax and it is not a Id based call this will not work. The url in the console is the correct url, meaning it is going to the proper location. I think it is looking for a page called Save rather than going to the ActionResult. In this case i do not need a view for this.
I am looking to see if i am correct about it looking for a page and not the ActionResult and if so is there a way i can get this to look at the ActionResult instead of a page.
Maybe a way to pass something to the javascript file that gets the url and then use that in the saveAjax script.
To add to this below is the data-hmi-action which is used on all the buttons in the project.
init: function() {
$("[data-hmi-action]").each(function () {
on = "click";
if (this.dataset.hmiOn) on = this.dataset.hmiOn;
$(this).on(on, HMI.Gui[this.dataset.hmiAction]);
if (this.dataset.hmiShortcut)
{
$(document).bind('keydown', this.dataset.hmiShortcut, HMI.Gui[this.dataset.hmiAction]);
$(window.FrameDocument, window.FrameWindow).bind('keydown', this.dataset.hmiShortcut, HMI.Gui[this.dataset.hmiAction]);
}
});
}
Thanks for your help!
Edit---
In this particular case i was experiencing a 500 server error because i was trying to capture HTML / Javascript that is on a page. Dot Net scans that information for fictitious characters. Code markup looks as though someone has passed information along with what you are trying to send as a threat.
It can be disabled. In my case it was adding
[ValidateInput(false)]
to the controller action. You can also cover the whole application by using in the web.config file.
<system.web>
<httpRuntime requestValidationMode="2.0" />
</system.web>
There are other ways to do this in different apps this example is for MVC only.
You can check out the address below for more details on other apps.
MSDN
I'm currently working on a website which should heavily rely on ajax. But I'm facing a problem which I cannot find a solution to online.
I'll now shamelessly post my (stripped) function to completely fetch a page.
function loadTemplate(name, replaceWholePage = true){
$.when( $.ajax({ url: "./templates/{0}/{0}.html".format(name), error: function() { console.error( "Could not load HTML file of template '{0}'!".format(name)); }}),
$.ajax({ url: "./templates/{0}/{0}.css".format(name), error: function() { console.error("Could not load CSS file of template '{0}'!".format(name)); }}),
$.ajax({ url: "./templates/{0}/{0}.js".format(name), error: function() { console.error("Could not load JS file of template '{0}'!".format(name)); }}) )
.then(function(html, css, js) {
var _css = "\n<style>\n" + css[0] + "\n</style>";
var _js = "\n<script>\n" + js[0] + "\n</script>";
if(replaceWholePage) {
$("#content").empty();
}
$("#content").append(html[0]);
$("#content").append(_css);
//$("#content").append(_js);
});
}
You see the line where it appends the js file is commented. But somehow the site still gets the js. When I comment that line out, my js code isn't actually twice in the document, but still gets called twice.
As Varinder stated, jQuery automatically recognised the fetched file as javascript and executed it. Setting the dataType to "text" in the call fixed it!
Thanks
I have a div element in my index.cshtml with id #myresults and i am trying to load data through jquery.load method by calling a mvc controller method. But i am not able to get the right syntax.
I am passing a custom object as a parameter as well.
var mycustomObject = {
obj1:value1,
obj2:value2,
..
}
The following does not work...(an i have tried other combinations as well..i get server not found error)
$("#myresults").load ('#Url.Action("MyActionMethod","Home")',mycustomObject);
while the following works
$("#myresults").load('/Home/MyActionMethod', mycustomObject);
While the last statement works, it works only on localhost.
Whats the right syntax to use for jquery load with Url.Action ?
#Url.Action() will always generate the correct url, so if your getting a 404, it means this code is in an external script file. Razor code is not executed in external scripts so your url would literally be the text "#Url.Action("MyActionMethod","Home")".
Options to solve this include
moving the code into the view or its layout
declaring a global variable in the view - var url =
'#Url.Action("MyActionMethod","Home")'; an in the external file use
$("#myresults").load(url, mycustomObject);
assign the url to an element as a data-* attribute, for example
<button type="button" id="loadSomething" data-url="#Url.Action("MyActionMethod","Home")">...</button>,and in
the external file
$('#loadSomething').click(function() {
var url = $(this).data('url');
$("#myresults").load(url, mycustomObject);
});
Define the div element as:
<div id="myresults" onload="loadMyData();"></div>
And make the ajax call in your method:
<script type="text/javascript">
function loadMyData() {
$.ajax({
cache: false,
url: '#Html.Raw(Url.Action(MyActionMethod","Home"))',
data: { obj1:value1, obj2:value2 },
dataType: "json",
type: 'post',
success: function (result) {
if (result.success) {
$('#myresults').html(result.data);
}
else {
alert("Failed to load data!");
}
}
});
}
</script>
This is my website ( work in progress ) -> Link
I use this my code, written on the basis of another creator. -> Link
Ajax Code
$.ajax({
type: 'GET',
url: href,
cache: true,
}).done(function (data) {
......
// Run scripts
$data.filter('script').each(function(){
var scriptTag = document.createElement('script');
scriptTag.text = $(this).html();
document.body.appendChild(scriptTag);
});
});
The code allows you to load the page via ajax, then without refreshing the page. The problem arises when the page has to load javascript, they are not considered and therefore the script in the loaded page does not work.
If I can (if it is not edited) I'll link the site where I'm working and try to click in the first written EdoNetowork, then a link to an account in the topic and you'll see that the code is ignored.
How can I fix?
I think the problem is in updating the javascript page to load. But how can I recharge sources are loaded via javascript src?
You are using $data.filter('script') which is not returning anything, instead use find and in your function you are using $(this).html() but as script has no html inside it so it will not give you anything, instead access attr('src') and append it to your script tag
// your function
$data.filter('script').each(function(){
var scriptTag = document.createElement('script');
scriptTag.text = $(this).html(); // use $(this).attr('src')
// scriptTag.attr('src', $(this).attr('src')) // use it like this
document.body.appendChild(scriptTag);
});
you can also load javascript in your done callback in ajax call usinf jquery getScript()
$.ajax({
.. }).done(function () {
$.getScript( "ajax/test.js", function( data, textStatus, jqxhr ) { ... })
});
This works on my dev machine, but not on a production server. I am trying to update some divs with ajax, but they are not updated, though other parts work fine. I am using IIS 6 on the server.
When I debug this code on the server side with firebug, it does not hit any breakpoints I add to the success function.
Script:
function updateServiceInfo(nodeId) {
var id = { id: nodeId };
$.ajax({
url: '/ServiceInfo/ServiceInfoPartial',
type: 'GET',
data: id,
dataType: 'html',
success: function (data) {
$('#serviceInfoContent').html(data);
},
error: function (request, error) {
}
});
}
Controller:
public class ServiceInfoController : Controller
{
public ActionResult ServiceInfo()
{
return PartialView("ServiceInfo");
}
public ActionResult ServiceInfoPartial(string id)
{
return PartialView("ServiceInfoPartial");
}
}
Views:
serviceinfopartial
#model string
<p>
Немає опису</p>
serviceinfo
<div id="serviceInfo">
<div id="ContainerPanel" class="ContainerPanel">
<div id="serviceInfoHeader" class="collapsePanelHeader">
<div id="dvHeaderText" class="HeaderContent">
Опис сервісу</div>
<div id="dvArrow" class="ArrowClose">
</div>
</div>
<div id="serviceInfoContent" class="serviceInfoContent">
</div>
</div>
</div>
The response that is returned in the console is
GET http://localhost/Managers/GetManagers?nodeId=563344 404 Not Found 42ms
Ahhhhhhhhhhhhhh, another hardcoded url:
url: '/ServiceInfo/ServiceInfoPartial',
Never hardcode urls like this in an ASP.NET MVC application.
Always use url helpers to generate them:
url: '#Url.Action("ServiceInfoPartial", "ServiceInfo")',
or if this is in a separate javascript file where you cannot use url helpers simply use HTML5 data-* attributes on some DOM element:
<div id="serviceInfo" data-url="#Url.Action("ServiceInfoPartial", "ServiceInfo")">
...
</div>
and then in your javascript simply:
url: $('#serviceInfo').data('url'),
The reason your code doesn't work when you host it in IIS is because in IIS you are probably hosting your application in a virtual directory so the correct url is no longer /ServiceInfo/ServiceInfoPartial but is /YourAppName/ServiceInfo/ServiceInfoPartial. That's the reason why you should never hardcode any url and use helpers to generate them => it's because helpers handle this cases. Another benefit of using helpers is that if you later decide to change the layout of your routes in Global.asax you won't need to modify all your javascript files, etc... Your url managment is centralized in a single location.
This worked for me, but only tested in Chrome 53:
Create some global scope variables in your .cshtml file, just be mindful of scope issues and give your variables unique names.
<script>
globalUrl = '#Url.Action("ServiceInfoPartial", "ServiceInfo")';
</script>
Then reference your js file...
<script type="text/javascript" src="yourJsFile.js"></script>
Inside your yourJsFile.js:
url: globalUrl,