I have some Javascript code shown below. It uses a replacement variables from the model which are working fine - however I cannot work out how to get the content location from the model. I have
function drawChart() {
$.post('#Url.Content("~/Home/GetDataAssets")', function (d) {
var data = google.visualization.arrayToDataTable(d);
var options = {
title: '#Model.Title',
width: '#Model.Width',
height: '#Model.Title',
allowHtml: #Model.AllowHtml,
is3D: #Model.Is3D
};
But I want the #Url.Content line to look something like
$.post('#Url.Content("#Model.ContentLocation")', function (d) {
Which doesn't work as it thinks that #Model.ContentLocation is a string. When I try escaping the quotes I do not get the required result as they are being Html encoded. I believe that is because I am doing it incorrectly.
What is the correct way to encode the quotes so that the data will be read from the location in the model variable?
With the help of Stephen Muecke I have got this working. The line making the post should have been:
$.post('#Url.Content(Model.ContentLocation )', function (d)
JavaScript does not understand MVC "~/..." path syntax. If your intention is to use that in Ajax post or get you need to get the actual path of that virtual path. To do that, you can do this from the server side code when you setup the model:
var urlHelper = new UrlHelper(Request.RequestContext);
var model = new ModelClassNameHere {
ContentLocation = urlHelper.Content("~/blah/nicepic.jpg") };
return View(model);
One other thing that I'd suggest is to cache all these server side model properties into a global page setting in JavaScript as to centralized things and not having #Model.blah everywhere. Beside if you are going to split your javascript files into multiple files during development, this is just good practice.
See this example: https://dotnetfiddle.net/ZlOL0n
I am using angular.module.value to cache that global pageSettings that contains server side model contents so I can pass them around in angular. See how the settings value are injected into the controller.
Related
I was wondering if there were any good techniques in keeping your WebAPI controller routes in sync with the client side.
For instance, you have a WebAPI controller BooksController. On the client you could invoke a method by calling the endpoint:
$.get('books/1');
Then one day you decide to rename the controller, or add a RoutePrefix. This breaks the client side code, as the endpoint has changed.
I came across the library WebApiProxy, which looks interesting. Does anyone have a good approach to solving this problem? Is there a reason to use string literals on the client that I may be overlooking?
I created a blog bost on te subject. Take a look :)
http://blog.walden.dk/post/2017/02/02/export-all-your-asp-net-webapi-endpoints-to-json
Im working on a post consuming it in javascript.. Anyway, this code exports the endpoints runtime, and will work on refactorings and route changes. It exports uri parameters as well, they can be used to be parsed in javascript and replaced with values from the client.
The simplest way to achieve waht you want, is to use the built-in ApiExplorer in ASP.NET WEBAPI. It searches for all "ApiController" implementations, and reads the route-attribute metadata.
public class EndpointManager
{
public IEnumerable<ApiMethodModel> Export()
{
//Use the build-in apiexplorer to find webapi endpoints
IApiExplorer apiExplorer = GlobalConfiguration.Configuration.Services.GetApiExplorer();
//exclude endpoints without the attribute
var apiMethods = apiExplorer.ApiDescriptions.Select(ad => new ApiMethodModel(ad)).ToList();
return apiMethods;
}
}
You can create an endpoint that returns that generated data.
[RoutePrefix("api/endpoint")]
public class EndpointApiController : ApiController {
[HttpGet]
[Route("all")]
public IEnumerable<ApiMethodModel> All()
{
var endpoints = new EndpointManager().Export();
return endpoints;
}
}
Now all the endpoints can be reached at "/api/endpoint/all"
Here is an sample I was talking about in my comment to your question:
function getUrl(uri) {
var bookRoute = /books(.*?)/i;
var otherRoute = /something(.*?)/i;
if(uri.match(bookRoute)) {
return uri.replace(bookRoute, "http://localhost/webapi/books$1")
}
if(uri.match(otherRoute)) {
return uri.replace(otherRoute, "http://mydomain/api/something$1")
}
return uri;
}
alert(getUrl("books/1"));
alert(getUrl("something/realy/different/1"));
All you need is to define the routes in the body of your function.
Any help will be appreciated.
I need to extract data from websites and found that node-unfluff does the job (see https://github.com/ageitgey/node-unfluff). There is two ways to call this module.
First, from command line which works!
Second, from node js which doesn't work.
extractor = require('unfluff');
data = extractor('test.html');
console.log(data);
Output : {"title":"","lang":null,"tags":[],"image":null,"videos":[],"text":""}
The data returns an empty json object. It appears like it cannot read the test.html.
It seems like it doesn't recognise test.html. The example says, "my html data", is there a way to get html data ? Thanks.
From the docs of unfluff:
extractor(html, language)
html: The html you want to parse
language (optional): The document's two-letter language code. This
will be auto-detected as best as possible, but there might be cases
where you want to override it.
You are passing a filename, and it expects the actual HTML of the file to be passed in.
If you are doing this in a scripting context, I'd recommend doing
data = extractor(fs.readFileSync('test.html'));
however if you are doing this in the context of a server or some time when blocking will be an issue, you should do:
fs.readFile('test.html', function(err, html){
var data = extractor(html);
console.log(data);
));
I have a server side function which returns content of HTML page:
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
Meteor.methods({
sayHello: function() {
var response = Meteor.http.call("GET", "http://google.com");
return response;
}
});
});
And I have client code where I am trying to get title from this HTML page:
'click .add_tag' : function(e,t) {
//Session.set('editing_tag_id', e.target.id);
Meteor.call("sayHello", function(err, response) {
var title = $(response.content).find("title").text();
var title2 = $(response).find("title").text();
var title3 = response.content.match(/<title[^>]*>([^<]+)<\/title>/)[1];
alert(title3);
});
I would like to get jQuery version ('title' or 'title2'), but it doesn't works. It returns empty string.
'Title3' - version works fine, but I don't like regexps. :)
Is there any way to make 'jQuery'-versions works ?
As requested, I will reiterate my comment as an answer...
I would stick with the regex, even though you don't like it. There is a huge overhead of constructing a DOM element that is essentially an entire page, purely for the purpose of parsing a small amount of text. The regex is more lightweight and will perform adequately in slower browsers or on slower machines.
Wrap response.content in a <div> and then do a selection off of that. This way you have a proper structure to start from rather than an array that you might actually be getting.
var $wrap = $("<div></div>").html(response.content);
$wrap.find("title").text();
An example of what is probably going on: http://jsfiddle.net/UFtJV/
Don't forget one thing : you should never return HTML to client. You should return Json (or even Xml) that your client will transform into Html using Template.
You are doing like a lot of dev doing Bad Ajax.
Don't forget : "only data on wire, not display".
So there should not be any problem coz, on response you just have to take data from Json formatted response and inject it inside your Template.
I need to generate a JSON object from server containing data to be cached on client. I placed the following:
<script src='Path to js file on server" />
At the server, I generated my json data and placed them inside the JS file.
I can see the generated JSON object on the client-side something as:
var jsonData = [{}, {}];
However, when I try to access jsonData object, it says, undefined!
Is there another way to generate valid javascript from server side?
Thanks
This is the server-side code:
var items = List<myObj>();
string json = JsonConvert.SerializeObject(items, Formatting.Indented);
StringBuilder sb = new StringBuilder();
sb.AppendLine();
sb.AppendFormat(" var jsonData = {0};", json);
var fileName = Request.PhysicalApplicationPath + "Scripts/Data.js";
System.IO.File.WriteAllText(fileName, sb.ToString());
As for client side:
<script src='#Url.Content("~/Scripts/Data.js")' type="text/javascript"></script>
I tried to use this code on the client:
alert(jsonData[0].Id);
It says, jsonData is undefined!
Regards
ASP part is ok, the problem seemed to lie in javascript variable scoping plane. Possible problems:
You just don't include that js file.
You're trying to access variable before it is initialized;
Variable isn't visible in place, you're trying to access it.
You're not exact in your question and accessing not jsonData, but something like jsonData[0].property
etc.
UPD: Ok, first two options are excluded. Where are you trying to access this variable? Please, show us a portion of code.
I am semi-new to ASP.NET MVC. I am building an app that is used internally for my company.
The scenario is this: There are two Html.Listbox's. One has all database information, and the other is initally empty. The user would add items from the database listbox to the empty listbox.
Every time the user adds a command, I call a js function that calls an ActionResult "AddCommand" in my EditController. In the controller, the selected items that are added are saved to another database table.
Here is the code (this gets called every time an item is added):
function Add(listbox) {
...
//skipping initializing code for berevity
var url = "/Edit/AddCommand/" + cmd;
$.post(url);
}
So the problem occurs when the 'cmd' is an item that has a '/', ':', '%', '?', etc (some kind of special character)
So what I'm wondering is, what's the best way to escape these characters? Right now I'm checking the database's listbox item's text, and rebuilding the string, then in the Controller, I'm taking that built string and turning it back into its original state.
So for example, if the item they are adding is 'Cats/Dogs', I am posting 'Cats[SLASH]Dogs' to the controller, and in the controller changing it back to 'Cats/Dogs'.
Obviously this is a horrible hack, so I must be missing something. Any help would be greatly appreciated.
Why not just take this out of the URI? You're doing a POST, so put it in the form.
If your action is:
public ActionResult AddCommand(string cmd) { // ...
...then you can do:
var url = "/Edit/AddCommand";
var data = { cmd: cmd };
$.post(url, data);
... and everything will "just work" with no separate encoding step.
Have you tried using the 'escape' function, before sending the data? This way, all special characters are encoded in safe characters. On the server-side, you can decode the value.
function Add(listbox) { ...
//skipping initializing code for berevity
var url = "/Edit/AddCommand/" + escape(cmd);
$.post(url);
}
use javascript escaping, it does urlencoding.
Javascript encoding
Then in C# you can simple decode it.
It will look as such
function Add(listbox) { ...
//skipping initializing code for berevity
var url = "/Edit/AddCommand/" + escape(cmd);
$.post(url);
}
Have you tried just wrapping your cmd variable in a call to escape()?
You could pass the details as a query string. At the moment I'm guessing you action looks like:
public virtual ActionResult AddCommand( string id )
you could change it to:
public virtual ActionResult AddCommand( string cmd )
and then in you javascript call:
var url = "/Edit/AddCommand?cmd=" + cmd;
That way you don't need to worry about the encoding.
A better way would be if you could pass the databases item id rather than a string. This would probably be better performance for your db as well.