Relative URL inside $ajax with asp.net mvc 3 - asp.net-mvc-3

I know one can use this function
#Url.Action("MyInfo", "Home")
to avoid the hardcoding of urls, but my $.ajax calls are in a separate .js file. Would the above still work?
From my knowledge, the #Url.Action will only work inside the Razor file. But considering that we are advised to use non-obtrusive JS, I am not quite sure how I would use the #Url.Action.
Please advise.

Would the above still work?
No.
From my knowledge, the #Url.Action will only work inside the Razor file
Your knowledge is correct.
But considering that we are advised to use non-obtrusive JS, I am not
quite sure how I would use the #Url.Action.
You could use HTML5 data-* attributes on some DOM element that you are unobtrusively enhancing (unless this element is already a <form> or an anchor in which case it already contains an url):
<div id="foo" data-url="#Url.Action("foo")">Hello</div>
and then in your separate javascript file:
$(function() {
$('#foo').click(function() {
var url = $(this).data('url');
// TODO: do something with the url
});
});

Add a function parameter for the relative paths. E.g., in your View:
<script type="text/javascript">
var path = "#Url.Action("ActionName", "ControllerName")";
someAjaxMethod(path)
</script>
and in your external js file:
function someAjaxMethod(path)
{
var data = {};
$.ajax(path, data)
}

Related

laravel passing a variable to js file from a controller

I have a js file located in assets folder (not View). can i pass a varible from a controller?
In view file:
The Js is called like this
<canvas id="chart1" class="chart-canvas"></canvas>
</div>
It is not possible (in my point of view) to put a variable to external JS file. You can use data-... attributes and get values from html elements.
For example you can pass your PHP variable as a json encoded string variable in your controller.
$data['chart_info'] = json_encode($chart_info);
return view('your_view', $data);
Then put it in data-info like this.
<canvas id="chart1" class="chart-canvas" data-info="{{ $chart_info }}"></canvas>
And finally in JS, you can get the variable and decode (parse) it as following.
let canvas = document.getElementById('chart1');
let info = JSON.parse(canvas.dataset.id);
console.log(info);
You can put that part of the Javascript in the view and send the variable to the same view. For example, add a section in view:
#section('footer')
<script type="text/javascript">
</script>
#endsection
Do not forget that you should add #yield('footer') to the end of your layout view.
I don't like to mix javascript and PHP/Blade, it might be hard to read the code in the future... You could use a different approach, loading the chart with a async ajax request.
You will have to create a end-point that returns the data you need for your chart:
Your router:
Route::get('/chart/get-data', [ ControllerName::class, 'getChartData' ]);
Your controller method:
public function getChartData() {
$chartData = [];
// Your logic goes here
return $chardData;
}
In your javascript (using jquery) file there will be something like that:
function loadChartData() {
$.ajax({
'url': '/chart/get-data',
'method': 'GET'
})
.done((data) => {
// Load your chart here!!!
})
.fail(() => {
console.log("Could not load chart data");
});
}
Hope I helped ;)

Using MVC3, how to get browsers to explicitly interpret a transferred script as HTML?

In my MVC app, I am returning some Javascript. Howveer, I am using the anti-forgery token on the view, so the rendered result would be
<input name="__RequestVerificationToken" type="hidden" value="E8as+4Ff1u/c/+kuFcNXXCREB5pz5GAfH2krN5RvzURJaHZSApuRc4czZqmoITaKdy0XhN5sFfRzl4ne+wB3PkWOscBWzoIxUk3hGaFwDxRXSbMs8K9IwojEAtV5u57MR7hiSujr6MOTpjjbf5FPaYgO4gmH6lSR9mbSyO2IedI=" />
<script type="text/javascript">
// Here, we ensure that jQuery is loaded then load up the rest of our JS in in order.
ord = Math.random() * 10000000000000000;
...
So there is some HTML to be added to the page then the JS.
The issue is that I get the following notification in Chrome:
Resource interpreted as Script but transferred with MIME type
I need the browser to interpret this as HTML in order to make use of the anti-forgery token.
I have tried putting this on the view:
<%#Page Title="" Language="C#" ContentType="text/xml" %>
Which renders:
<%System.Web.WebPages.DynamicPageDataDictionary`1[System.Object] Title="" Language="C#" ContentType="text/xml" %>
<input name="__RequestVerificationToken" type="hidden"
...
...but the same message persists.
In my controller I have also tried:
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
Byte[] bytes = encoding.GetBytes(page.clientScript);
return new ContentResult
{
ContentType = "text/xml", // also tried text/html
Content = Encoding.UTF8.GetString(bytes),
ContentEncoding = System.Text.Encoding.UTF8
};
Same issue.
-- UPDATE --
This is how I'm invoking the MVC app to return the text:
// used to load scripts on to the client script using a non-blocking asynch request
(function() {
function async_load(){
var s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = 'http://myserver/MyAppPath/someids';
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
}
if (window.attachEvent)
window.attachEvent('onload', async_load);
else
window.addEventListener('load', async_load, false);
})();
If I've understood correctly, you need an MVC action which returns both html and a script tag that can be injected in a page via a <script... include. You also want to render this via an MVC view.
The biggest issue you've missed is that in order to get this content into the calling page, you need to execute document.write from the script - you can't just send back HTML and script in response to the script include - the browser won't understand it, it's expecting javascript only.
There are a few ways to do this - I have written a full suite of ViewContent MVC controller methods, with the same overloads as View which returns the result of a view to a controller action as a string. I can then pass that back as a string literal (useful for html email generation) but also to a javascript encoder.
In this case, you don't need to be so generalist. We can leverage Darin Dimitrov's answer to this SO: Embed MVC Partial View into a document.write JS call and split your view into a View and a partial. The view writes the document.write() skeleton, and the partial view renders the dynamic html you want to be injected into the page. It's unclear if you're using the Anti Forgery Token in the main view which will call the script (in which case it should be rendered as part of the view that it returns) or if you're actually hard-coding it in the script. The second should definitely not be used but I'm writing this answer as if it is, because that appears to be what you want.
First, your partial view (let's call it Fragment.cshtml, put it in ~/Views/Shared)
<input name="__RequestVerificationToken"
type="hidden"value="[ommitted]" />
<script type="text/javascript">
// Here, we ensure that jQuery is loaded then load up the rest of our JS in in order.
ord = Math.random() * 10000000000000000;
...
Second, the host view, called SomeIds.cshtml
#{ Response.ContentType = "text/javascript"; }
document.write('#Html.Raw(HttpUtility.JavaScriptStringEncode(Html.Partial("~/Views/Shared/Fragment").ToHtmlString()))')
Now this view returns a document.write call that injects the HTML returned by the Fragment.cshtml into the page that includes the script.
Are you returning a PartialView that has all of the markup rendered?
Create a PartialView with your (form and script includes) and in your Controller:
public ActionResult Index(Models.MyModel model)
{
// validate the model if needed
return PartialView("[My PartialView Name]", model);
}
You could put your scripts in separate files, and add the [script src] tags in the PartialView.

MVC3 routes interfering with JS paths

I have the following route defined:
routes.MapRoute(name: "StateResults", url: "{state}/{searchTerm}", defaults: new { controller = "Results", action = "SearchState" });
In one of my shared chtml files I have the following defined:
<script src="#Url.Content("Scripts/jquery-1.5.1.js")" type="text/javascript"></script>
I understand why the JS is not getting loaded, but how do I get around this? I get around this?
Thanks.
You can ignore routes for JS
IgnoreRoute("{file}.js");
As an alternative method you can use the constraint parameter to avoid files ending with js
routes.MapRoute("StateResults", "{state}/{searchTerm}",
new { controller = "Results", action = "SearchState" },
new { searchTerm = #".*?([^js])$" }); // regex not tested
RouteCollectionExtensions.MapRoute Method (RouteCollection, String, String, Object, Object) from MSDN
constraints
Type: System.Object
A set of expressions that specify values for the url parameter.
you need to set up the routes that it ignores .js files.
a good description is found here:
http://weblogs.asp.net/rashid/archive/2009/04/03/asp-net-mvc-best-practices-part-2.aspx
something like this will do the trick:
routes.IgnoreRoute("{file}.js");

How do I get the correct URL for an MVC action when using Jquery/AJAX?

So I have my first MVC2 site that I'm working on and naturally I'd like to throw some AJAX in there. The problem is, is that I don't know how to get the URL for the action when passing in a URL parameter. Let me explain. The examples I've seen so far show the developer passing in strings like '/MyController/MyAction'. That's great, except if your controllers are not in the root directory of your website (as is the case in my situation). I could always use relative URLs like 'MyAction' except if the URL contains parameters that doesn't work either. Consider http://example.com/myroot/MyController/MyAction vs http://example.com/myroot/MyController/MyAction/PageNumber/SomeOtherValue. Now the relative URL will be incorrect.
In the ASPX code, this is easy. I just write in <%= Url.Action("MyAction") %>. But how do I do this in my javascript file?
This is part of the long-standing issue that including server-sided code in JavaScript files is not really possible :(. (Without serious hacks, that is.)
The best solution is to include the action URL inside your HTML file somewhere, then get that value from JavaScript. My suggestion would be something like this:
<!-- in your view file -->
<form id="MyForm" action="<%: Url.Action("MyAction") %>"> ... </form>
<!-- or -->
<a id="MyLink" href="<%: Url.Action("MyAction") %>"> ... </a>
combined with
// In your .js file
$("#MyForm").submit(function ()
{
$.post($(this).attr("action"), data, function (result) { /* ... */ });
return false;
});
// or
$("#MyLink").click(function ()
{
$.getJSON($(this).attr("href"), data, function (result) { /* ... */ });
return false;
});
This feels semantically clear to me, and in some cases even creates degradable fallback behavior for when JavaScript is turned off.
You can't do this in your JavaScript file directly, however you can pass these dynamic values into your script by way of a script initializer. Consider the following example:
External Js file
ShoppingCart = function() {
this.settings = {
AddProductToCartUrl: '',
RemoveFromCartUrl: '',
EmptyCartUrl: '',
UpdateCartUrl: ''
};
};
ShoppingCart.prototype.init = function(settings) {
this.settings = jQuery.extend(this.settings, settings || {});
};
HTML/View
<script type="text/javascript">
var cart = new ShoppingCart();
cart.init({ AddProductToCartUrl: '<%=Url.Action("MyAction")%>' });
alert(cart.settings.AddProductToCartUrl);
</script>
Simple: tell your javascript what the correct URL is.
Tactically, you can get there alot of ways, but they basically break down into two techniques:
Have a server-side generated javascript "configuration" so you can do something like var url = siteConfiguration.SITEROOT + 'products/pink-bunny-slippers' Note this file can be a normal MVC view, the only trick is you have to tell the controller to send a text/javascript header rather than text/html.
Basically, dependency inject it into your script. IE function wireUpAjaxLinksToService(linkIdentifier, serviceEndpoint) where you call using something like wireUpAjaxLinks('a.ajax', '<%= Url.Action("MyService", "Services") %>')

Ajax append load

it must be jquery
I have file text.html with 6 div in (a,b,c,d,e,f)
In another file i have a div, i like it to populate the content of a+b+c+d+e+f into that single div
I have try .load = but b remplace a
i have try append, but i need a temp var
so now i am stuck
That code get the content from the file textes.html ... div #a and put the content into div #right, but the second libe REMPLACE the content of right a with right b
I like to append the content a + b NOT a over b
$(document).ready(function(){
var temp = load('textes.html #nicolas');
$('#right').append(temp);
var temp = load('textes.html #antoine');
$('#right').append(temp);
.
.
.
.
return false;
});
that code is the idea behind what should work, but i cannot make a ajax .load() to load content into a variable to append the content to the div...
<script type="text/javascript">
$(document).ready(function(){
$.ajax({
url: "textes.html",
cache: false,
success: function(html){
$("#right").append(html);
}
});
});
</script>
That code load the WHOLE html file, i like to get only some selected DIV #
$(document).ready(function(){
$.get("textes.html",function(data){
$("#right").append($("#nicolas",data)).end().append($("#antoine",data));
},'html');
});
I had a similar issue just now and I think I figured out a way to do what we want using the .load() function. It's not pretty but never mind ;)
First off, I added a "TempDiv" to my html with a "visibility:hidden" style.
<div id="TempDiv" style="visibility:hidden"></div>
Then you run the jQuery :
$(document).ready(function(){
$('#TempDiv').load('textes.html #nicolas', function(){
$('#right').append($('#TempDiv').html());
});
});
I'm not sure it's the best way !
PS : That is my first stackoverflow post ;)
try,
$.get('url.php', function(data) {
$("#right").append(data);
});
This sounds like jQuery? Please state what framework you are using since I can't really see any mention of it. Anyway, append should work. Just do something like:
mydiv.append(a.text());
mydiv.append(b.text());
mydiv.append(c.text());
mydiv.append(d.text());
mydiv.append(e.text());
mydiv.append(f.text());
They should all be appended into mydiv.
NOTE: if you also want the html, use the .html() function instead of .text().
JQuery ( http://jquery.com/ ) is a good javascript library that you can use to do an AJAX request to get the other file. See this question for more: Use jQuery to replace XMLHttpRequest

Resources