When converts ASP.NET values of ValueProvider? - c#

My project uses ASP.NET MVC.
I´m sending some data via ajax to a controller-action which looks like
{ "data" : { "DATE" : "\/Date(1409097600000)\/", "NAME" : "thomas } }
I use the ValueProvider of the controller to process the data:
var provider = ControllerContext.Controller.ValueProvider;
var value = provider.GetValue("data.DATE");
// value is now already "27.08.2014 00:00:00"
Why?
Where does this part of conversion happens?
Similar question to that :-
The data above is as content type "application/json; charset=utf=8"
Having data as "application/x-www-form-urlencoded; charset=utf=8" ASP.NET is not able to convert the date-values.
_model.DATE=%5C%2FDate(1409097600000)%5C%2F&_model.NAME=thomas
I think I made something wrong concerning the \ and / in the .NET-date-format: \/Date(1409097600000)\/
(I know netwonsoft.json could be an alternative for javascript-serialization, but unfortunately not at the moment)

If you are sending JSON data to the server using an Ajax post, then the content-type header should reflect that fact (Content-Type="application/json; charset=utf=8"), so that the server interprets the data correctly.
Content-Type="application/x-www-form-urlencoded; charset=utf=8", is for submitting data via an HTML form. If you submit your JSON data with this content type header, the browser will url-encode it and produce the string you illustrated:
_model.DATE=%5C%2FDate(1409097600000)%5C%2F&_model.NAME=thomas
The Date() function has no meaning in an HTTP form post (it is a JSON function) which is why the date conversion fails.

Related

How to return a JSON endpoint in Vue using axios

I'm creating a web application using VueJS, C# and Entity Framework, but there is a problem. I don't know how to return a JSON using Axios to backend. In this project I'm using dynamic forms based on JSON schema and what I'm trying to do is when the user has completed the required fields, once he clicks on the 'send' button, that generated JSON should be redirected to my database where it should parse into a table with it's values.
Here is the function that "should" return the completed JSON but no success
returnJSON(){
axios
.post('http://localhost/jsonSchema/email.json')
.then(response => (this.info = response))
}
I'm not allowed to share more code, but i can provide a link from where I took the JSON schema:
https://github.com/koumoul-dev/vuetify-jsonschema-form. I've tried json server as well, but no success, because once I change those fields into objects, the schema is not working anymore.
I have two questions:
How can I return a link that contains the resulted JSON?
Should I look at this problem from another point of view? Is it better to parse JSON first in C# then send that data to database instead of sending just an endpoint to be parsed directly into a stored procedure?
Basically, the json schema does not affect how you send data back to the backend server, it just enforces that the data (form data in this case) follows a certain structure. Therefor:
Simply look at your form v-model:
<v-jsf v-model="model" :schema="schema" :options="options" />
...which is model in this case. This variable holds your data. Now send it to the server in your submit method:
async returnJSON(){
this.info = await this.$axios.post('<YOUR SERVER URL>', this.model).then(response => response.data)
}
Note that I changed your returnJSON method to use async/await syntax, which is far more understandable here and also made it use response.data aswell as called axios in the way I suspect you need to call it (depending on your setup).

Call C# function from Javascript in aspx webform and then reload page

Trying to figure out how to call a c# function in a webform. I tried both ajax and windows.location but could just be off on my path. Trying to send it my c# code at SpeakerList.aspx/update and then gonna attach two variables i have in javascript which shouldnt be too bad. But want it to hit the C# function then reload the page so hoping there is just an easy call im missing.
buttons: {
"Save": function () {
var combo = ASPxClientControl.GetControlCollection().GetByName('DropDownList1');
var value = combo.GetSelectedItem().value;
var billID = $("#billID").val();
window.location = "SpeakerList.aspx/updateRec";
}
You might want to try using WebMethods:
http://aspalliance.com/1922_PageMethods_In_ASPNET_AJAX.all
This allows you to call a function in your page's code behind using JavaScript.
Assuming you are using MVC, you probably want to return a JSON result. An easy way to consume Json within your client webpage is using JQuery. You can return JSON as as the output of a webpage, but I don't recommend it. Create a separate service point that repesents the JSON method.
It is hard to tell what you are actually trying to accomplish, but the normal usage pattern for a JSON method is the supply the parameters as part of the querystring (which you can refactor with routing if you want). The result is then just a JSON packet.
Personally, I like JSON.Net for server side JSON, but you don't actually need this. Look up JSONMethod for examples, etc. that will show you how to do this.
From the browser client, JQuery has a json method, but I personally recommend using the more generic ajax method a JQuery so you can use the handlers for success, error and completion. E.g.
$.ajax({
url: "http:...",
data: queryparm,
cache:false,
timeout:15000,
success: function(data){
jresult = $.parseJSON(data);
...
},
error:function (xhr, ajaxOptions, thrownError)
{
setErrorMsg("Error getting search results: " + thrownError);
}
});
EDIT -- Actually, I've done this exact same thing with webforms too, code is essentially identically (if you use JSON.Net on the server side). You don't have the routing options to make the urls REST compliant, but as an internal json web service, you probably won't really care about that.
As a webpage (.aspx) page, you can use a "postback" this is the simplest method for a web form. You can always declare some hidden fields to use for data passing if you are not passing back a native "control" value. If you don't know how to do this, you need to read a tutorial on using web forms.

include asp.net filled javascript file

I have a javascript file (marker.js) which contains a json variable :
var markers = [
['Service1', 46.81865, -71.31838367115952],
['Service2', 46.81248956788163, -71.29209432884048],
['Service3', 46.80349635182245, -71.26580498652137],
['Service4', 46.81248956788163, -71.39725169811672],
['Service5', 46.821482783940814, -71.40138736927624]
]
In the main javascript, I insert this javascript file so main function can use it. => OK
Now, I want to fill dynamically this var so the coordinates are dynamically get from the database and inserted in the file. Of course, this file should not be written on the disk as an other user would need the same file but with different coordinates.
I think I should tell the server this js file should be interpreted by the asp engine and data retrieved in the codebehind then sent to the "js interface" but how do I do that?
I would appreciate an example of both a home page and the js.
Thank you for your help!
I would return JSON from the controller and include a method in the include file that accepts JSON like so:
function someFunction(json){
var jsonObj = JSON.parse(json);//object is built from json returned by the controller
}
You can call this controller method using AJAX when the main view loads and pass in the JSON from the ajax call

How to pass complex model from client to server?

I have some data "Foo" that I want to pass from the browser to the server and retrieve predicted statistics based on the information contained within foo.
$.ajax({
type: 'GET',
url: "/api/predictedStats/",
data: "foo=" + ko.toJSON(foo, fooProperties),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function(data) {
return _this.viewModel.setPredictedStats(data);
},
error: function(jqXHR, statusText, errorText) {
return _this.viewModel.setErrorValues(jqXHR, errorText);
}
});
I created a predicted stats controller and get method taking an argument of Foo.
public class PredictedStatsController : ApiController
{
public PredictedStats Get(Foo foo)
{
return statsService.GetPredictedStats(foo);
}
}
Sticking a breakpoint on the Get method I see the Foo object is always null. There are no errors thrown from the webapi trace logging just the following lines.
WEBAPI: opr[FormatterParameterBinding] opn[ExecuteBindingAsync] msg[Binding parameter 'foo'] status[0]
WEBAPI: opr[JsonMediaTypeFormatter] opn[ReadFromStreamAsync] msg[Type='foo', content-type='application/json; charset=utf-8'] status[0]
WEBAPI: opr[JsonMediaTypeFormatter] opn[ReadFromStreamAsync] msg[Value read='null'] status[0]
I've no problem sending the data via a post to the Foo controller to create the Foo object on the server so I can say there's nothing wrong with the json created clientside.
Looking in fiddler the resulting Get looks like the following where jsondata is the object foo.
GET /api/predictedStats?foo={jsondata} HTTP/1.1
Is this even possible or am I going about this all wrong?
Thanks
Neil
EDIT:
I feel like I almost got this working with the following
public PredictedStats Get([FromUri]Foo foo)
{
return statsService.GetPredictedStats(foo);
}
The object foo was coming back fine but no properties of Foo were being populated properly.
In the mean time I've resorted to using a POST with near identical data just dropping the "foo=" and this is working just fine.
I'm not sure whether the POST or the GET should be used in this case but that would be interesting to know.
I also found this http://bugs.jquery.com/ticket/8961 which seems to suggest you can't attach a body to a GET request with jquery so POST is probably the only sensible option
You almost got there :)
When you use [FromUri] (which you have to use for 'complex' objects because by default Web API doesn't 'bind' complex objects, it's always looking to deserialize them from the body) you don't need to pass param= in the Uri - you just pass the members of the value as query string parameters. That is 'member1=value&member2=value' - where member1 and member2 are members of the Foo.
Note there is no 'bug' in jQuery - while the HTTP spec doesn't prohibit a request body, it's likely that the browser does (and if that's the case, the jQuery can't send it), and it's more than likely that a server will never read it anyway. It's just not accepted practise. It also has interesting issues with caching potentially, as well, in that a browser won't cache a POST, PUT, DELETE etc, but will cache a GET if the response headers don't prohibit it - that could have serious side effects for a client application. I recommend you look at this SO: HTTP GET with request body for more information and some useful links on this subject.
Equally, when using jQuery - you don't need to convert the object to JSON either - just pass the javascript object in the data member of the options and jQuery turns it into the correct format.
Or should that be, Web API understands the format the jQuery passes it as.

Using .ajaxForm and C# MVC, how can I prevent Internet Explorer from trying to save Json result?

I'm returning some Json via a C# MVC Controller. Other browsers work fine, but Internet Explorer (IE9) tries to Save the returned Json data as a Text file. Any ideas how to keep this from happening?
//MVC Controller Code...
return Json(new { redirectToUrl = Url.Action("Create", "Album",
new { url = url, isLocalFile = isLocalFile})});
//Clientside Javascript Code
$("#uploadImageForm").ajaxForm({
beforeSubmit: function () {
},
success: function (data, textStatus, xhr) {
window.location.href = data.redirectToUrl;
},
error: function (data, textStatus, xhr) {
}
});
I've tried adding "text/plain" and "text/json" to the second argument of the return Json method, it doesn't work.
Many thanks!
Quote from the documentation of the jquery.form plugin:
Browsers that support the XMLHttpRequest Level 2 will be able to
upload files seamlessly and even get progress updates as the upload
proceeds. For older browsers, a fallback technology is used which
involves iframes since it is not possible to upload files using the
level 1 implmenentation of the XMLHttpRequest object. This is a common
fallback technique, but it has inherent limitations. The iframe
element is used as the target of the form's submit operation which
means that the server response is written to the iframe. This is fine
if the response type is HTML or XML, but doesn't work as well if the
response type is script or JSON, both of which often contain
characters that need to be repesented using entity references when
found in HTML markup.
To account for the challenges of script and JSON responses when using
the iframe mode, the Form Plugin allows these responses to be embedded
in a textarea element and it is recommended that you do so for these
response types when used in conjuction with file uploads and older
browsers. Please note, however, that if there is no file input in the
form then the request uses normal XHR to submit the form (not an
iframe). This puts the burden on your server code to know when to use
a textarea and when not to.
This means that if your form contains file input fields and you are submitting this form to a controller action that returns JSON, you must wrap this JSON in a <textarea> tags.
So your response should not look like this:
{ "redirectToUrl":"some url" }
it should look like this:
<textarea>{ "redirectToUrl":"some url" }</textarea>
In order to achieve that you could use a custom action result that will wrap the response with those tags:
public class TextareaJsonResult : JsonResult
{
public TextareaJsonResult(object data)
{
this.Data = data;
}
public override void ExecuteResult(ControllerContext context)
{
var response = context.HttpContext.Response;
bool shouldWrap = !context.HttpContext.Request.IsAjaxRequest();
if (shouldWrap)
{
response.Write("<textarea>");
}
base.ExecuteResult(context);
if (shouldWrap)
{
response.ContentType = "text/html";
response.Write("</textarea>");
}
}
}
and then have your controller action return this custom result:
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
// ... some processing
var redirectToUrl = Url.Action(
"Create",
"Album",
new { url = url, isLocalFile = isLocalFile }
);
return new TextareaJsonResult(new { redirectToUrl = redirectToUrl });
}
Now obviously in your AJAX success callback you also need to account for this difference by testing the typeof result and in the case of a legacy browser (such as Internet Explorer) manually parse the response. You may take a look at the source code of the page I have linked to.
But this being said, I can see that in your success callback you are redirecting to a controller action contained in the JSON response returned by the server. Here comes my question: What's the point of using AJAX in the first place if you are going to redirect? Why don't you use a standard form post to the controller action and have the controller action directly perform the redirect? AJAX should be used when you want to stay on the same page.
I agree with Jesse's comment, this is probably a duplicate of the link he provided.
As such I'll provide an alternative. I prefer to view json coming over the wire using a http proxy similar to fiddler http://www.fiddler2.com/fiddler2/ . I mention fiddler because it works with all browsers. The advantage is that you get a treeview of the parsed json. It's MUCH easier to read and find what you're looking for.
Also, I believe firebug for firefox, chrome dev tools, and ie dev tool all provide the same functionality. (I know chrome has the treeview, I think I remember firebug having it, and I would be surprised if modern IE doesn't have it considering the other 2 do.)

Categories