ASP.NET 4.0 routing + ajax + browser history - ajax

The problem with ASP.NET 4.0 routing is that the Page.RouteData.Values does not contain the paramenters after # character from the link
System.Web.Routing.RouteTable.Routes.MapPageRoute("ProjectViewRoute1",
"project/{title}/{idProject}#{idDesign}", "~/ProjectView.aspx");
As I said, the Page.RouteData.Values.ContainsKey("idDesign") will return false
The reason I want to make use of this feature is because I use JavaScript and Ajax to hide some content and load new one, wich in eyes of an user is like loading a different page, and he must be able to copy paste the URL and view that page later.
The question is: how to get the {idDesign} from the RoutedData ?

Browsers don't send data after the # in the URLs to the server; as a result, it is not possible for ASP.Net to capture that data and provide it to you.
I would recommend using a ? instead of your # to get the functionality you need, and include an AJAX call to capture data placed in the hash section of the url to send to the server, if necessary, for AJAX-created urls.
Using jQuery:
$(function () {
if (location.hash) {
hash = location.hash.substr(1);
location.hash = null;
location.search = hash;
}
});

Related

Django - AJAX - Why do I need url parameter?

It's my first time using AJAX and I don't understand why I need to specify url parameter in a JS Ajax call.
{% block javascript %}
<script>
$("#id_username").change(function () {
$.ajax({
url: '/some_new_url/',
data: {
'something': ...
},
success: function (data) {
if (data.is_taken) {
alert("Data is already in DB");
}
}
});
});
</script>
{% endblock %}
To my understanding, AJAX is used to do something on the server side without refreshing a page. So it shouldn't redirect to a new url upon sending a data to the server, and stay on the same url. And yet AJAX call requires url parameter.
And I don' really like this, because setting a new url means I have to add another url pattern in my app/urls.py.
re_path(r'^create/$', views.Some_View.as_view(), name='create'),
And as a consequence, make another view in my views.py
class Some_View(ListView):
model = SomeModel
fields = '__all__'
But, I already have a CBV that generates form fields on the user side and accepts user inputs. I only want to make my existing CBV to save data to DB using AJAX call.
Since I don't understand what the purpose of the url is, I don't know how to set up my new url pattern, and CBV. Can I get some explanation here?
++ This is just a bonus question, but my ultimate goal is to generate multiple form fields, and multiple Submit buttons that sends the respective form input data to the server using AJAX. If there's any advice on how to tweak AJAX code, I would appreciate it.
An AJAX request is just a regular HTTP request to a url on the server. The only difference between an AJAX request and a request made by an ordinary browser GET or POST is that with AJAX, the results that come back from the server are returned to your javascript function and then you get to decide what to do with those results.
So there's no automatic updating of anything.
If you want to save something on the server, you need a view there on the server which is capable of understanding the data you are sending in the AJAX request, saving it, and then sending back a response which, again, your javascript code needs to be able to understand.
But if you already have a view which is capable of doing what you want, you can use it for your AJAX request, you just have to send a request with everything in it that the view requires.

How to use NodeJS with node-rest-client methods to post dynamic data to front end HTML

I am rather new to NodeJS so hopefully I am able to articulate my question(s) properly. My goal is to create a NodeJS application that will use the node-rest-client to GET data and asynchronously display it in HTML on client side.
I have several node-rest-client methods created and currently I am calling my GET data operation when a user navigates to the /getdata page. The response is successfully logged to the console but I'm stumbling on the best method to dynamically populate this data in an HTML table on the /getdata page itself. I'd like to follow Node best practices, ensure durability under high user load and ultimately make sure I'm not coding a piece of junk.
How can I bind data returned from my Express routes to the HTML front end?
Should I use separate "router.get" routes for each node-rest-method?
How can I bind a GET request to a button and have it GET new data when clicked?
Should I consider using socket.io, angularjs and ajax to pipe data from the server side to client side?
-Thank you for reading.
This is an example of the route that is currently rendering the getdata page as well as calling my getDomains node-rest-client method. The page is rendering correct and the data returned by getDomains is successfully printed to the console, however I'm having trouble getting the data piped to the /getdata page.
router.get('/getdata', function(req, res) {
res.render('getdata', {title: 'This is the get data page'});
console.log("Rendering:: Starting post requirement");
args = {
headers:{"Cookie":req.session.qcsession,"Accept":"application/xml"},
};
qcclient.methods.getDomains(args, function(data, response){
var theProjectsSTRING = JSON.stringify(data);
var theProjectsJSON = JSON.parse(theProjectsSTRING);
console.log('Processing JSON.Stringify on DATA');
console.log(theProjectsSTRING);
console.log('Processing JSON.Parse on theProjectsSTRING');
console.log('');
console.log('Parsing the array ' + theProjectsJSON.Domains.Domain[0].$.Name );
});
});
I've started to experiment with creating several routes for my different node-rest-client methods that will use res.send to return the data and the perhaps I could bind an AJAX call or use angularjs to parse the data and display it to the user.
router.get('/domaindata', function(req, res){
var theProjectsSTRING;
var theProjectsJSON;
args = {
headers:{"Cookie": req.session.qcsession,"Accept":"application/xml"},
};
qcclient.methods.getDomains(args, function(data, response){
//console.log(data);
theProjectsSTRING = JSON.stringify(data);
theProjectsJSON = JSON.parse(theProjectsSTRING);
console.log('Processing JSON.Stringify on DATA');
console.log(theProjectsSTRING);
console.log('Processing JSON.Parse on theProjectsSTRING');
console.log('');
console.log('Parsing the array ' + theProjectsJSON.Domains.Domain[0].$.Name );
res.send(theProjectsSTRING);
});
});
I looked into your code. You are using res.render(..) and res.send(..). First of all you should understand the basic request-response cycle. Request object gives us the values passed from routes, and response will return values back after doing some kind of processing on request values. More particularly in express you will be using req.params and req.body if values are passed through the body of html.
So all response related statements(res.send(..),res.json(..), res.jsonp(..), res.render(..)) should be at the end of your function(req,res){...} where you have no other processing left to be done, otherwise you will get errors.
As per the modern web application development practices in javascript, frameworks such as Ruby on Rails, ExpressJS, Django, Play etc they all work as REST engine and front end routing logic is written in javascript. If you are using AngularJS then ngRoute and open source ui-router makes work really easy. If you look closely into some of the popular MEAN seed projects such as mean.io, mean.js even they use the ExpressJS as REST engine and AngularJS does the rest of heavyweight job in front end.
Very often you will be sending JSON data from backend so for that you can use res.json(..). To consume the data from your endpoints you can use angularjs ngResource service.
Let's take a simplest case, you have a GET /domaindata end point :
router.get('/domaindata',function(req,res){
..
..
res.json({somekey:'somevalue'});
});
In the front end you can access this using angularJS ngResource service :
var MyResource = $resource('/domaindata');
MyResource.query(function(results){
$scope.myValue = results;
//myValue variable is now bonded to the view.
});
I would suggest you to have a look into the ui-router for ui front end routing.
If you are looking for sample implementation then you can look into this project which i wrote sometime back, it can also give you an overview of implementing login, session management using JSON Web Token.
There are lot of things to understand, let me know if you need help in anything.

How can I get HTML element value inside Angular JS conroller while the page is getting loaded

Let me tel the scenario where I am stuck, I will try to explain simply rather than telling the actual.
1st : I am on page 1. Where few subjects are there with unique names.
2nd : I will click on one subject, which will call an struts2 action (lets call it ActionA)at back end with the unique subject name as a request parameter(Request type = GET).
3rd : Action A will only redirect to "Tutorial page".
4th : While loading it will make an AJAX call to another Struts2 action (lets call it ActionB), which will return JSON containing tutorials for that Subject.
Problem: As I am calling ActionA first and passing the subject name which is just redirecting the page to some other page. On page load I am calling another action to get the JSON. I am not able to get the request parameter value at ActionB that is the one which is returning JSON.
Note: I am using Struts2-JSON plugin thats why not need two actions, one for redirecting the page another for getting the JSON at page load.
Solution tried: I have tried to get the request parameter value that is the Subject name, putting a hidden field in the Tutorial page. But unable to get the value from inside the Angular JS controller.
Here is the example for a shared Service: http://plnkr.co/edit/P2ItVj20RYCJVjdIaXfY
But you are right if you reload the page this doesn't work. I think your scenario needs tweaking if you want to use angular or any other single page framework for that matter. One purpose of single page applications is to minimize reloads, preferable none. If your action A only returns a template where you then want to input the result of action B, I recommend looking at ngRoute or uiRouter, where you define a template (result of action A) and a controller for that view. This template than replaces a section of your page (ng-view) with the new template. If both are new to you I would recommend looking at uiRouter, it is similar but it gives you a lot more possibilities. Both provide a "resolve" function where you can load your action B before the page is rendered.
Code from plunker
angular.module("app", [])
.controller("MainController", ['SharedService', function(SharedService) {
var vm = this;
//bind to service
vm.service = SharedService;
}]);
Service
angular.module("app")
.factory("SharedService", [function() {
var service = {
id: "test"
}
return service;
}]);

How to get a HTTPRequest JSON response without using any kind of template?

I am new to Django but i am advanced programmer in other frameworks.
What i intend to do:
Press a form button, triggering Javascript that fires a Ajax request which is processed by a Django View (creates a file) that return plain simple JSON data (the name of the file) - and that is appended as a link to a DOM-Element named 'downloads'.
What i achieved so far instead:
Press the button, triggering js that fires a ajax request which is process by a Django view (creates a file) that return the whole page appended as a duplicate to the DOM-Element named 'downloads' (instead of simple JSON data).
here is the extracted code from the corresponding Django view:
context = {
'filename': filename
}
data['filename'] = render_to_string(current_app+'/json_download_link.html', context)
return HttpResponse(json.dumps(data), content_type="application/json")
I tried several variants (like https://stackoverflow.com/a/2428119/850547), with and without RequestContext object; different rendering strats.. i am out of ideas now..
It seems to me that there is NO possibility to make ajax requests without using a template in the response.. :-/ (but i hope i am wrong)
But even then: Why is Django return the main template (with full DOM) that i have NOT passed to the context...
I just want JSON data - not more!
I hope my problem is understandable... if you need more informations let me know and i will add them.
EDIT:
for the upcoming questions - json_download_link.html looks like this:
Download
But i don't even want to use that!
corresponding jquery:
$.post(url, form_data)
.done(function(result){
$('#downloads').append(' Download CSV')
})
I don't understand your question. Of course you can make an Ajax request without using a template. If you don't want to use a template, don't use a template. If you just want to return JSON, then do that.
Without having any details of what's going wrong, I would imagine that your Ajax request is not hitting the view you think it is, but is going to the original full-page view. Try adding some logging in the view to see what's going on.
There is no need to return the full template. You can return parts of template and render/append them at the frontend.
A template can be as small as you want. For example this is a template:
name.html
<p>My name is {{name}}</p>
You can return only this template with json.dumps() and append it on the front end.
What is your json_download_link.html?
assuming example.csv is string
data ={}
data['filename'] = u'example.csv'
return HttpResponse(simplejson.dumps(data), content_type="application/json")
Is this what you are looking for?

ASP.NET MVC AJAX calls without static Controller URLs (magic strings)

Question:
What is a clear, safe and systematic way to call my MVC controllers/actions from JavaScript, but keep the related URLs in a central place for updating when controllers change? Or to dynamically generate the URLs at run-time? Or to get compile-time checking for AJAX controller linkage?
Research/Past Attempts:
I've recently plugged in T4MVC to my MVC project. Great! Compile-time checking for controller linkage in my views - but I still have controller URLs littered all over my JavaScript. Worse, I have evolved how I do it over the project lifetime, so I do it multiple ways that I'm still not satisfied with.
1) One way:
locationAutoComplete = new AjaxQueue({
Controller: "Utilities", // null for current controller
Action: "GetMatchingLocations",
DataModel: null, // null for raw JSON, or a local model to populate
MaxQueuedRequests: 0
});
2) Another way:
locationAutoComplete = function (location) {
return $.ajaxPost(resolveUrl("~/Utilities/GetMatchingLocations"));
}
3) Both 1 and 2 above make use of a project root defined in a Master/Layout JavaScript snippet, but still use unchecked URL strings. So now I've started benefiting from T4MVC by simply defining controller strings in my .CSHTML view:
var locationLookupController = #Url.Action(MVC.Utilities.GetMatchingLocations());
4) The SO article ( Ajax call Into MVC Controller- Url Issue ) addresses this a little. It talks about method 3, but also suggests using the AjaxHelper namespace. Since I make heavy use of jQuery AJAX with some pretty customized interactions (e.g. loading results into a local data model, not at a click event but at a timed interval), I don't think it will help me much. Today I don't even include the MS AJAX JavaScript code on any of my pages.
Thanks!
Continue to use T4MVC. Mix it in with a little jQuery and HTML5 data-* attributes. Here's an example:
<div data-location-lookup-url="#Url.Action(MVC.Utilities.GetMatchingLocations())">
...
locationAutoComplete = function (location) {
var url = $('[data-location-lookup-url]').data('location-lookup-url');
return $.ajaxPost(url);
}

Resources