Hopefully this is a fairly easy question. Pardon my ignorance, but I am mostly a PHP/Zend developer, so i am struggling a little in C# and Visual Studio with a json/ajax issue. Is there something obvious I am missing? Any help will be appreciated. Should I be looking at List<>?
Here is the error I receive when I fire the javascript ajax function:
"Unknown web method getwidgets."
I have a dataset in C#, that I run through a JSON converter method. This works well and returns my data in a JSON string.
private widgetsBL widgetsBLObject = new widgetsBL();
[WebMethod]
public String getwidgets()
{
DataSet results = new DataSet();
results = widgetsBLObject.selectTheWidgets();
string jsresults = MyClassLibrary.JqueryTools.GetJSONString(results.Tables[0]);
return jsresults;
}
Here is the jsresults:
{"Table" : [ {"widgetid" : "1","widgetname" : "gizmo1000","widgetdescription" : "very cool widget"},
{"widgetid" : "2","widgetname" : "gizmo2000","widgetdescription" : "decent widget"},
{"widgetid" : "3","widgetname" : "gizmo3000","widgetdescription" : "terrible widget"} ]}
My Javascript call:
$.ajax({
type: "POST",
url: "my.aspx/getwidgets",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
// do stuff with returned data
}
});
getwidgets needs to be static
[WebMethod]
public static String getwidgets()
Remember that if you want your method to be exposed to calls from JavaScript, you need to mark your method with ScriptMethodAttribute. Thus making it look like this:
[ScriptMethod]
[WebMethod]
public static String getwidgets()
{
// Your core here
}
I would return in the method, the object itself and not not a serialized version of it because ASP.NET will JSON serialize it for you if you mark it as [ScriptMethod]; so in the client your variable data.d will contain the object itself and not a simple string that later you have to deserialize, as in your current implementation.
You are mixing technologies: my.aspx is for rendering HTML content, but it can be used to implement REST functionality.
In your case, the easiest would be to implement your code as part of the Page_Loaded() method. Make sure you clear the response first (so you don't have any additional markup in the response). Furthermore, you might want to set the content type of your response to JSON (rather than the default html):
protected void Page_Load(object sender, EventArgs e)
{
Response.ClearContent();
Response.ContentType = "application/json";
DataSet results = new DataSet();
results = widgetsBLObject.selectTheWidgets();
string jsresults = MyClassLibrary.JqueryTools.GetJSONString(results.Tables[0]);
return jsresults;
}
Then retrieve you JSON string at my.aspx (no getwidgets).
Also, since you are not posting any data, consider using GET rather than POST in your AJAX call.
Related
Question: Can we bind without the use of a model and just purely based on the parameter names of the IActionResult method. From the below I am posting a single string to the end point, however it is wrapped in a object with a property of reviewNotes. I have a work around at the moment, which is explained below.
I have setup the end point llike so.
[HttpPost("updateassetnotes/{id}")]
public IActionResult UpdateAssetNotes(int id, [FromBody]string reviewNotes)
{
_dataMapper.UpdateAssetNotes(id, reviewNotes);
return ApiSuccess("Updated Review Notes");
}
And the client side is posting like this.
var url = "/api/cataloguing/updateassetnotes/" + id;
var data = { reviewNotes: self.assetReviewNotes() };
$.ajax({
type: 'POST',
url: url,
data: JSON.stringify(data),
contentType: 'application/json'
}).done(function (resp) {
}).fail(function (resp) {
}).always(function () {
});
However if I change the data to:
var data = self.assetReviewNotes();
Then the review notes string is actually populated. As mentioned this is the work around im using at the moment. As previously mentioned I could create a simple model like the below and use this in the end point to bind the string. Im just wondering if there is a way to bind directly to the primitive types.
public class SimpleModel {
public string ReivewNotes {get;set;}
}
Obviously, as you already noted in your question
var data = { reviewNotes: "foo" };
is different from
var data = "foo";
as the latter is a string and the former is an object with a string property.
The most straightforward solution to your code comes to this line
data: JSON.stringify(data),
You could solve this by "unwrapping" the string out of the object by doing something like
data: JSON.stringify(data.reviewNotes),
The alternative is to avoid using JSON.stringify and just deal with the mapping the raw data instead. However, if you go this route, you may need to watch out for the mapping, and the [FromBody] decorator may need some tweaking, along with the content-type.
I have a controller class that I get data from database and return it in a function, Now I want to call this function in a js and set the data in variables to show in a page:
My code looks like: exampleController.cs
namespace iSee.WebApiHse.Controllers
{
public class expController : StandardController
{
public expController(
first myService,
ISystemSettings systemSettings,
IService myExpService)
{
_myService = MyService;
_systemSettings = systemSettings;
_myExpService = myExpService;
}
// GET data
public ActionResult Myexample(int id)
{
var elementIds = _systemSettings.ExpIds;
var myElements = CacheService.AllVisibleElements
.Where(x => elementIds.Contains(x.Id)).ToList();
var container = _kpiContainerService.Find(id);
var result = _myService.MonthByContainer(myElements, container);
return AsJson(result);
}
}
}
This works and I get the data. Now I have myExp.js that I need to use these data in it. How can I do that?
Thanks
You need to execute $ajax(..) (jquery syntax) request to your controller to pass and get compute information from the server.
For this your controller method, that you're going to call, has to be exposed for HTTP access.
More details on :
How to call controller method from javascript
Do you want work with your controller in View by JavaScript? It isn't good idea. You should pass Model to View and work with it or ajax and recieve json-data
An example that uses jQuery-ajax to call your C# method:
// javascript
var id = 987;
$.ajax({
url : '/expController/Myexample/',
type : 'GET',
data { id : id },
dataType : 'json', // <-- tell jQuery to decode the JSON automatically
success : function(response){
console.log(response);
}
});
This would call your method, passing in the value of id, then it would decode the JSON into the response object.
For plain Javascript ajax (no jQuery) see MDN Ajax.
You need to make a request to the Action Myexample. Usually this is done via AJAX:
In your view you could have:
function makeAJaxCall(idToSend) {
$.ajax({
url: '#Url.Action("exp", "Myexample")',
data: { id : idToSend },
type: "POST",
success: function(data) {
$("#HTMLElement").val(data.YourData);
}
});
}
Your response will come back in the data variable if the AJAX call succeeds. I have provided an example to show you how to change the value of an HTML element with the ID HTMLElement.
To invoke the function you can do:
makeAjaxCall(100);
You may load the JSON data in a var and pass it to the function in expjs.js, as:
var data = data_from_ajax();
exp_js_function(data);
data_from_ajax() would receive JSON data from your controller and action method.
Please consider this as a starting point and not as a copy-paste solution
I am sending some data from jquery.ajax to aspx, parsing there and writing on response, but that data is coming in error part, I think some error is being occured which is not being shown, but the correct data is getting returned in error part. Code is below.
JQUERY
var json = "{'uname':'" + $("#uname").val() + "','pwd':'" + $("#pwd").val() + "'}";
alert(json);
$.ajax({
type: "POST",
url: "DataProcess.aspx?Save=1",
data: json,
contentType: "application/json; charset=utf-8",
dataType: "json",
async: false,
success: function (msg) {
alert(msg);
},
error: function (msg) { alert("failed: " + msg.responseText); }
});
DataProcess.aspx.cs
namespace Test
{
public partial class DataProcess : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
ProcessAjaxRequest();
}
private void ProcessAjaxRequest()
{
if (Request.ContentType.Contains("json") && Request.QueryString["Save"] != null)
SaveMyData();
}
private void SaveMyData()
{
System.IO.StreamReader sr = new System.IO.StreamReader(Request.InputStream);
string line = "";
line = sr.ReadToEnd();
JObject jo = JObject.Parse(line);
Response.Write(line);
Response.Write((string)jo["uname"]);
Response.Write((string)jo["pwd"]);
}
}
}
So i am getting what ever the response is in the error part, what is wrong?
K i got the problem, above code is correct, Now my other doubt is, can i call a particular nonstatic method from this same aspx.cs, I mean when i tried something like this "DataProcess.aspx/Test?Save=1". It gives error saying not a web method, I declared method as
[WebMethod]
public void Test(){
}
K guys, I thought the problem was gone, just now i observed that, if i write a string to response something like this Response.Write("success"), its comming in jquery error block, but when i write something like this "Response.Write(0);", its comming in success block. The first one should also come, someone explain whats the problem
Thanks
not sure the exact problem but your json looks like a string. it should be like this
var json = {'uname':'" + $("#uname").val() + "','pwd':'" + $("#pwd").val() + "'};
I am assuming that you have already figured out about PageMethods (i.e. a static method decorated with WebMethod keyword).
Regarding your later question, its not possible to use non-static (instance) methods as Page Methods. The reason is quite simple - an instance method could access instance variables including control tree. Without view-state, ASP.NET cannot guarantee a correct control tree state in post-back scenarios. For such needs, UpdatePanel is the way to go - as it provides AJAX within the ASP.NET control model. Page Methods are meant for stream-lined communication where request/response data are minimalistic without overheads (i.e. the only meaningful data that you wants to communicate between client/server).
I've spent the last night trying to figure this out.
Basically in Google Maps, I am able to generate directions, or waypoints, between two points that the user chooses in client side Javascript.
I ideally want to be able to store these in my database ( Im using C#.NET and SQL Server DB ) by passing these to a server side C# method..
I've got to the point where I can put the directions I need into a string by using:
*var string = JSON.stringify(response);*
Now, here's where I'm stuck.
How do I pass this to a C# webforms method?
I've seen an MVC C# solution to my problem as:
var str = JSON.stringify(data)
var city = {};
city.Directions = str;
$.ajax({
type: 'POST',
url: 'usertrip.aspx/GetDirections',
data: str ,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (r) {
alert(r.d.Directions);;
}
});
But I've tested, and have concluded that this won't work for webforms. Does anyone know how I can alter this code so that I can pass the string to a Webforms method and not MVC?
Thanks!
You can definitely do this kind of thing with webforms. The important thing is that you need to set up a webservice that exposes methods that can be hit by the ajax call. This awesome article called Using jQuery to directly call ASP.NET AJAX page methods proved invaluable for me to figure out how to accomplish what you're trying to do.
For an example (from the article) doing something like this:
public partial class _Default : Page
{
[WebMethod]
public static string DoSomething(string myJsonData)
{
// deserialize your JSON
// do something cool with it
}
}
Would allow you to hit the webmethod with your AJAX call. I can assure you that I've done this in many different asp.net solutions what don't use MVC so with a little bit of tinkering you should be able to get the information you need to your code behind.
You would need to do something like :
var str = JSON.stringify(data)
var city = {};
city.Directions = str;
$.ajax({
type: 'POST',
url: 'usertrip.aspx/GetDirections',
data: { city: str },
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (r) {
alert(r.d.Directions);;
}
});
And in the Webforms code behind:
City city = new JavaScriptSerializer().Deserialize<City>(Request.Form["city"]);
Edit: Ok, so it looks like posting as application/json needs to be handled server side separate than a form. Is there any better way to post a form in C# as a complicated object? String:String just doesn't cut it. For example, I want to be able to use Dictionary to produce:
{
"data_map":{"some_value":1,"somevalue":"2"},
"also_array_stuffs":["oh look","people might", "want to", "use arrays"],
"integers_too":4
}
---OP---
I've looked on SO and other places. I'm just trying to POST a JSON string to a URL, but the server side keeps interpreting the content as a string instead of a query dict. We have other clients that aren't in c# that hit the server side fine (in HTML, JS, Objective-C, Java), but for some reason the POST data comes back wonky from the C# client.
C# source:
private static Dictionary<string,object> PostRequest(string url, Dictionary<string, object> vals)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(BaseURL+url);
httpWebRequest.ContentType = "application/json; charset=utf-8";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = JsonFx.Json.JsonWriter.Serialize(vals);
//json = json.Substring(1,json.Length-1);
streamWriter.Write(json);
streamWriter.Close();
}
try
{
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
string response = streamReader.ReadToEnd();
Dictionary<string,object> retval = JsonFx.Json.JsonReader.Deserialize<Dictionary<string,object>>(response);
return retval;
}
}
catch(WebException e)
{
}
return null;
}
This gets called like:
public static void Main (string[] args)
{
Dictionary<string,object> test = new Dictionary<string, object>();
test.Add("testing",3);
test.Add("testing2","4");
Dictionary<string,object> test2 = PostRequest("unitytest/",test);
Console.WriteLine (test2["testing"]);
}
For whatever reason, this is the request object that gets passed though:
<WSGIRequest
GET:<QueryDict: {}>,
POST:<QueryDict: {u'{"testing":3,"testing2":"4"}': [u'']}>,
COOKIES:{},
META:{'CELERY_LOADER': 'djcelery.loaders.DjangoLoader',
'CONTENT_LENGTH': '28',
'CONTENT_TYPE': 'application/json; charset=utf-8',
'DJANGO_SETTINGS_MODULE': 'settings.local',
'GATEWAY_INTERFACE': 'CGI/1.1',
'HISTTIMEFORMAT': '%F %T ',
'HTTP_CONNECTION': 'close',
'LANG': 'en_US.UTF-8',
'QUERY_STRING': '',
'REMOTE_ADDR': '127.0.0.1',
'REMOTE_HOST': '',
'REQUEST_METHOD': 'POST',
'RUN_MAIN': 'true',
'SCRIPT_NAME': u'',
'SERVER_PORT': '9090',
'SERVER_PROTOCOL': 'HTTP/1.0',
'SERVER_SOFTWARE': 'WSGIServer/0.1 Python/2.7.2+',
'SHELL': '/bin/sh',
'SHLVL': '1',
'SSH_TTY': '/dev/pts/0',
'TERM': 'xterm',
'TZ': 'UTC',
'wsgi.errors': <open file '<stderr>', mode 'w' at 0x7f3c30158270>,
'wsgi.file_wrapper': <class 'django.core.servers.basehttp.FileWrapper'>,
'wsgi.input': <socket._fileobject object at 0x405b4d0>,
'wsgi.multiprocess': False,
'wsgi.multithread': True,
'wsgi.run_once': False,
'wsgi.url_scheme': 'http',
'wsgi.version': (1, 0)}>
[18/Oct/2012 19:30:07] "POST /api/1.0/unitytest/ HTTP/1.0" 200 31
Some of the more sensitive data in the request has been removed, but is irrelevant
Ugh, I hope I don't make a habit of answering my own questions.
So, Posting Json this way is different than a normal form submission. That means if your server side is expecting just a normal form submission it will not work. The C# code does as it's intended to do, but only submits a JSON string as the POST body. While this may be convenient for people who validate, clean, and handle raw input anyway, keep in mind that if you're using a normal web framework, you will have to write an alternate condition to accept the raw string.
If anybody has an idea how to do a form submission in C# containing objects more complex than a hashmap/dictionary of strings, then I will upvote your answer and give you lots of hugs. For now, this hacky nonsense will have to do.
Well, once, a long time ago I implemented a banking app front end, which, made massive use of JSON for communication between client and server.
It was a clean way to find complex object to and from the server, no need to make complex cleanup or raw string processing.
The key was using WebServices designed for ajax on the server side, your web server class should look like this:
[WebService(Namespace = "http://something.cool.com/")]
[ScriptService] // This is part of the magic
public class UserManagerService : WebService
{
[WebMethod]
[ScriptMethod] // This is too a part of the magic
public MyComplexObject MyMethod(MyComplexInput myParameter)
{
// Here you make your process, read, write, update the database, sms your boss, send a nuke, or whatever...
// Return something to your awaiting client
return new MyComplexObject();
}
}
Now, on your client-side, set things up to make ASP.NET talk to you in JSON, I'm using JQuery for making the ajax requests.
$.ajax({
type: 'POST',
url: "UserManagerService.asmx/MyMethod",
data: {
myParameter:{
prop1: 90,
prop2: "Hallo",
prop3: [1,2,3,4,5],
prop4: {
// Use the complexity you need.
}
}
},
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function(response) {
alert(response.d);
}
});
Anything that ASP want to return as the result for your ScriptMethod, is going to be contained in the response.d variable. So, let's say you are returning from the server a complex object, "response.d" is the reference to your object, you access all the object members using the dot notation as usual.