Please be gentle, as I'm still new to web programming and -very- new to Ajax!
I've created a C# function which extracts data from an mssql database, formats it to a json string and returns that. Now I need to make a call from my javascript (jQuery) slider through an aspx page that is related to the C# code file.
I have actually never done anything like this before, from what I could tell by googling I need to use xmlHttpRequest, but how exactly do I make the function get hold of this string?
It would be awesome if someone had some example code that shows how this works.
The simplest way to do this is to convert your function into an ASHX file that writes the JSON to the HTTP response.
You can then call it using XmlHttpRequest, although you can call it much more easily using jQuery.
You can call it with jQuery like this:
$.get("/YourFile.ashx", function(obj) { ... }, "json");
It's relatively easy with jQuery if you mark the C# function as a [WebMethod] or make it part of a ASP.NET webservice. Both these techniques make it easy to have the response automatically converted into a JSON object by ASP.NET, which makes processing on the client easier (IMHO).
The example below is if the page has a WebMethod named GetData, but it's trivial to change the URL if you create a service.
$.ajax({ url: "somepage.aspx/GetData",
method: "POST", // post is safer, but could also be GET
data: {}, // any data (as a JSON object) you want to pass to the method
success: function() { alert('We did it!'); }
});
On the server:
[WebMethod]
public static object GetData() {
// query the data...
// return as an anonymous object, which ASP.NET converts to JSON
return new { result = ... };
}
Related
How do you properly create a Web API POST of complex object or multiple parameters using Angular2?
I have a service component in Angular2 as seen below:
public signin(inputEmail: string, inputPassword: string): Observable<Response> {
return this.http.post('/api/account/signin', JSON.stringify({ Email: inputEmail, Password: inputPassword}), this.options);
}
The targeted web api is seen below:
[HttpPost]
[Route("signin")]
public async Task<IActionResult> Signin(string email, string password)
{
....
}
This does not work because I need to convert the parameters of the web api into a single POCO class entity with Email and Password properties and put the [FromBody] attribute: Signin([FromBody] Credential credential)
Without using [FromURI] (POST requests with query strings?), how can I make POSTs of multiple parameters or complex objects without converting these parameters into a single POCO class?
Because what if I have numerous Web API POST actions with parameters like (string sensitiveInfo1, string name, int sensitiveInfo2) or (ClassifiedInfo info, string sensitiveInfo1, string sensitiveInfo2), do I need to convert them all to POCO classes and always use [FromBody]?
PS.
I was using RestangularJS before and it can posts anything (mulitple primitive objects and complex objects) without my Web API actions having [FromBody] attributes. Will about to investigate how RestangularJS do it.
Without using [FromURI] (POST requests with query strings?), how can I make POSTs of multiple parameters or complex objects without converting these parameters into a single POCO class?
I know its not what you want to hear but out of the box this is not possible. It is not a limitation of the browser code that is making the request. This means it does not matter if you are using Angular, JQuery, straight JavaScript, or even RestangularJS. This is a limitation (I use that word loosely as I am sure this is by design) of Web API (any version). Here is the documentation on this design: Parameter Binding in ASP.NET Web API by Mike Wasson.
At most one parameter is allowed to read from the message body. So this will not work:
// Caution: Will not work!
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }
So the question becomes, what are your options?
Create a model
This is the thing you were trying to avoid but I list it first because this is how Web API was intended to behave. I have not yet heard a compelling reason not to do this. This approach allows you to extend your model easily without having to change the method signature. It also allows for model validation on the model itself. Personally I really like this approach.
public class SignInModel{
public string Email {get;set;}
public string Password {get;set;}
}
[HttpPost]
[Route("signin")]
public async Task<IActionResult> Signin(SignInModel signInModel)
{
// ....
}
I did not repeat your existing JavaScript code because what you have works as is with the above web api code
URL
Again, what you were trying to avoid. This does make what you want possible with the limitation that you have to pass these parameters using the Query string on the URL. The JavaScript would change but the signature you had on the Web API method would not.
public signin(inputEmail: string, inputPassword: string): Observable<Response> {
return this.http.post('/api/account/signin/?email=inputEmail&password=inputPassword', null, this.options);
}
I did not repeat your existing Web API code because what you have works as is with the above web JavaScript code (by default FromUri is assumed I believe)
Custom Model Binder
See Passing multiple POST parameters to Web API Controller Methods by Rick Strahl. This option allows you to create a custom model binder that could do what you are asking. It is a whole bunch of extra code though for, IMHO, not much benefit. Maybe there are situations where it would be useful although I really cannot think of any off the top of my head.
Dynamic
Finally you could also pass in a dynamic object as the parameter of your Web API. This is essentially the same as receiving the JSON as a string and making your Controller code responsible for the deserialization of content. Again, I believe that this would make your code worse in most situations as you have to implement custom validation and type checks. This answer was proposed previously on SO by Bes Ley. Again, maybe there are situations where it would be useful although I really cannot think of any off the top of my head.
If you call Web API 2.2 post method from Angular 2 type script, dont forget to add following header content and parameter object.
let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
var params = new URLSearchParams();
params.set('userid', '102');
params.set('username', 'foo');
return this._http.post('http://localhost:6579/api/PostUser', params.toString(), { headers: headers }).map(res => res.json());
Perhaps you should post with options:
{
headers: new Headers({
'Content-Type': 'application/x-www-form-urlencoded'
})
}
and encode data like
jQuery.param({user:'bla', password: 'bla'});
WebAPI does not provide this out of the box. If you try to get understanding of web API bindings, you might be able to figure out why.
I think this article might help.
The generic rules are:
– simple, string-convertible parameters (value types, strings, Guids, DateTimes and so on) are by default read from URI
– complex types are by default read from the body
– collections of simple parameters are by default read from the body too
– you cannot compose a single model based on input from both URI and request body, it has to be one or the other
I have fixed the issue of Angular2 HTTP Post ASP.NET MVC Web API
let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
let params: URLSearchParams = new URLSearchParams();
params.set('value', '2');
let options = new RequestOptions({
headers: headers//,
//search: params
});
let content = new URLSearchParams();
content.set('StudentName', 'Inderjit Singh';
content.set('Mobile', '+919041165398');
content.set('Nationality', 'Indian');
content.set('AdmissionNo', '6');
content.set('SectionCode', '1');
content.set('Gender', 'Male');
content.set('RegNo', '18585');
content.set('ClassCode', '1');
this.http.post('YOUR_URL', content.toString(), { headers: headers }).map((res: Response) => { console.log("data is==>" + res.text()); }).subscribe();
WebApi will be able to deserialize your Credential object provided the JSON object has the same field names (I am not sure about case so you may be right here). You seem to be missing the headers from the post call in your Angular2 component.
Can you check the Content-Type using Chrome Debugger or Fiddler? It should be application/json.
Try this, passing a complex class object into a single data parameter.
var SearchQuery = function () {
this.Alphabet = null;
this.Search = false;
this.Keyword = null;
this.RegionList = null;
};
var para = new SearchQuery();
{ data: JSON.stringify(para) } - Post Data
you can receive it using a JObject in your API controller and deserialize it as according to your classes.
I wish to populate a JavaScript array with the results of a database query. From what I understand, a good approach is to populate a bunch of directories on my server with serialized XML or JSON files which my JS functions can then read into without having to access the database. Is this true? Should the database write these XML files upon user interaction, or should they be prepopulated?
From the details you have provided:
I Personally would create a Web Service endpoint returning your linq query serialized to JSON using JSON.NET or an equivalent. The endpoint can then be called using ajax within your client page.
You can check this example out on ASP.NET for how to create a asmx (legacy) web service. Also you can look at this example of using the [WebMethod] attribute .
A web method in your code behind files.
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string GetMyQueryResultsAsJson()
{
var results = GetQueryResults();
var jss = new JavaScriptSerializer();
string json = jss.Serialize(results);
return json;
}
A ajax call on your client page:
function loadData() {
var myArray = [];
$.getJSON("<%= ResolveUrl("~/MyPage.aspx/GetMyQueryResultsAsJson") %>", function (data) {
$.each(data, function(obj) {
myArray.push([obj.id, obj.someValue, obj.AnotherValue]);
});
});
}
I used jQuery ajax with generic http handler returing json
I created handler and put my business logic there.
It return me the result in form of json
I iterated the json using jquery.
And created my html form that.
Edit 1
Here are some useful links
http://www.codeproject.com/Articles/203621/Call-HTTPhandler-from-jQuery-Pass-data-and-retriev
http://www.sharepointnutsandbolts.com/2010/11/sp2010-ajax-part-4-returning-json-from.html
Edit 2
You can also take benefit of jtemplate
http://www.joe-stevens.com/2010/01/05/using-the-jtemplate-jquery-plugin-with-ajax-and-asp-net/
http://encosia.com/use-jquery-and-aspnet-ajax-to-build-a-client-side-repeater/
I have a partial view that when the user clicks a button, some data is passed to the database and the results returned. The results must be displayed in another partial view. The results are obtained using the following Controller method and Ajax script:
public ActionResult GetResultData(Models.SelectedFilterValues selectedFilters)
{
resultData = resultRepository.GetResultData(
selectedFilters.Projects,
selectedFilters.ExperimentTypes,
selectedFilters.StudySet,
selectedFilters.Species,
selectedFilters.Strain,
selectedFilters.Department,
selectedFilters.Location);
return PartialView("Results", resultData);
}
function GetResultData(selectedProjects, selectedExperiments, selectedStudySets, selectedDepartments, selectedLocations, selectedSpecies, selectedStrain) {
$.ajax({
type: "GET",
url: "/Search/GetResultData",
data: { projects: selectedProjects, experimentTypes: selectedExperiments, studySet: selectedStudySets,
department: selectedDepartments, location: selectedLocations, species: selectedSpecies, strain: selectedStrain
},
error: function (data) {
},
success: function (data) {
}
});
}
I keep getting the error when the data is returned into the Ajax method, is this because it is returning a partial view? What I want is for the Ajax method to accept the data, and then for me to pass that data into the new partial view. Is this possible?
Thanks.
I think you are mixing up client-side and server-side logic.
A partial view can contain logic that is executed on the server. Typically you would execute business logic in a Controller, and UI logic in the PartialView. For instance, any markup using Razor is actually executed on the server. The result then is HTML which is sent to the browser.
This HTML may contain client-side (JavaScript) code. So typically you would create a PartialView which contains JavaScript code that calls jQuery methods such as $.ajax(). When it does, it doesn't matter anymore how the JavaScript got to the browser -- as part of a PartialView or not, that doesn't matter. The JS code is executed on the client side, and it calls logic on the server side.
When the Ajax call returns data to the client side, the JS code there can then render the data into a grid, or apply a jQuery template, or do whatever with it that it wants. What it cannot do, is execute server-side PartialView code, because any PartialView has long since executed.
If I use jQuery AJAX to call a specific ASP.NET page method how to have that method return a value back to the AJAX method that called it?
Update
My situation is I have an existing web application with many existing methods. I would like to be able to use jQuery to execute some of these methods and then update the UI with the results. My mandate is to stay away from ASP.NET AJAX and stick with jQuery. Management is concerned about continued development and support with ASP.NET AJAX from Microsoft. I agree with them.
You can use JQuery with page methods this way: http://encosia.com/2008/05/29/using-jquery-to-directly-call-aspnet-ajax-page-methods/
The success callback contains a parameter with the returning data.
HTH.
There are two ways to skin this cat (that I am familiar with).
The ".Net Way" which involves a Web Method and a Script Manager (see here: http://geekswithblogs.net/frankw/archive/2008/03/13/asp.net-ajax-callbacks-to-web-methods-in-aspx-pages.aspx).
The "Old Skool Way" which involves simply writing a response out by determining what was called. Typically you'd use a framework like MVC so going to http://www.MyWebsite.com/Object/Method/Id can map back to Object.Method(id).
You can do this without a framework like MVC but it makes things a little more difficult and, if you go that route, you should really use an ASP.Net handler rather than an actual page (since you don't need the Aspx overhead). This is an Ashx file.
With pure ASP.NET (not talking WCF here) I'd go with a handler (ASHX) file, and use JSON as the interchange format. I won't get into the details of JSON (here is a decent start), but the idea is a lightweight handler on the server that generates json text and returns it to the client, which can then use the structure easily in javascript.
This is obviously a simplified example but the gist is the JSON can be data driven from the server and easily consumed by the javascript on the client.
server:
<%# WebHandler Language="C#" Class="Handler" %>
using System;
using System.Web;
public class Handler : IHttpHandler {
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/json";
context.Response.WriteFile("~/myData.json");
}
public bool IsReusable {
get {
return false;
}
}
}
client:
myData =
(function ()
{
var json = null;
$.ajax({
'async': false,
'global': false,
'url': "handler.ashx",
'dataType': "json",
'success': function (data) {
// this code is called when the
// data is returned from the server
json = data;
}
});
return json;
}
)();
alert(myData.MyArray[0].MyProperty);
In my particular situation, I have a couple of solutions to my problem. I want to find out which one is more feasible. In this case, I can also achieve my goal by returning a JSON object from my server side code; however, I do not know how it is done and what the best way of doing it is.
First off, I don't need a full aspx page as I only need a response returned from code. So, do I use web services, a handler, or is there any other specific way to do this?
Is this solution feasible? Do I build the JSON string using the StringBuilder class and inject that string into the target aspx page? Are there any precautions or things that I should be aware of?
I appreciate your ideas.
Regards,
Kemal
------------UPDATE !------------
Suppose I have a JSON object in my userlist.aspx page, which then I use with jQuery...
{"menu": {
"id": "color1",
"value": "color",
"popup": {
"menuitem": [
{"value": "Red"},
{"value": "Green"},
{"value": "Yellow"}
]
}
}} // example taken from the json.org/example page
Now when I want to add a new menu items from my aspx page, what do I do... I think this way my question is more specific...
Lets assume I create a new string in my aspx code, as such "{"value": "Blue"}. How do I inject this into the already existing itemlist in the target page? Or is this not the correct approach to this kind of situation? If not, how else can it be achieved?
Also, if I wanted to fire a jQuery event when a new item is added to this list, how is this achieved?
------------UPDATE 2 on 26 August 2015 ------------
By the time I asked this question, the way I was approaching the problem was in another aspect. I am now more proficient in the subject and can gladly accept the most voted answer since the approach to this question clearly should not include the already existing JSON and output a new one from the code as #DavGarcia also suggests.
In your Page_Load you will want to clear out the normal output and write your own, for example:
string json = "{\"name\":\"Joe\"}";
Response.Clear();
Response.ContentType = "application/json; charset=utf-8";
Response.Write(json);
Response.End();
To convert a C# object to JSON you can use a library such as Json.NET.
Instead of getting your .aspx page to output JSON though, consider using a Web Service (asmx) or WCF, both of which can output JSON.
no problem doing it with asp.... it's most natural to do so with MVC, but can be done with standard asp as well.
The MVC framework has all sorts of helper classes for JSON, if you can, I'd suggest sussing in some MVC-love, if not, you can probably easily just get the JSON helper classes used by MVC in and use them in the context of asp.net.
edit:
here's an example of how to return JSON data with MVC. This would be in your controller class. This is out of the box functionality with MVC--when you crate a new MVC project this stuff gets auto-created so it's nothing special. The only thing that I"m doing is returning an actionResult that is JSON. The JSON method I'm calling is a method on the Controller class. This is all very basic, default MVC stuff:
public ActionResult GetData()
{
var data = new { Name="kevin", Age=40 };
return Json(data, JsonRequestBehavior.AllowGet);
}
This return data could be called via JQuery as an ajax call thusly:
$.get("/Reader/GetData/", function(data) { someJavacriptMethodOnData(data); });
With ASP.NET Web Pages you can do this on a single page as a basic GET example (the simplest possible thing that can work.
var json = Json.Encode(new {
orientation = Cache["orientation"],
alerted = Cache["alerted"] as bool?,
since = Cache["since"] as DateTime?
});
Response.Write(json);
If you get code behind, use some like this
MyCustomObject myObject = new MyCustomObject();
myObject.name='try';
//OBJECT -> JSON
var javaScriptSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
string myObjectJson = javaScriptSerializer.Serialize(myObject);
//return JSON
Response.Clear();
Response.ContentType = "application/json; charset=utf-8";
Response.Write(myObjectJson );
Response.End();
So you return a json object serialized with all attributes of MyCustomObject.