I have a very simple WCF Data Services application and I am doing some basic CRUD operations. I have a ChangeInterceptor on the entity set that is changing, but the object in the ChangeInterceptor is the current state in the database, not what is sent in the HTTP PUT. Is there a way to validate the properties of the object before saving it?
Here is my ChangeInterceptor:
[ChangeInterceptor("People")]
public void OnChangePerson(Person personChanging, UpdateOperations updateOperations) {
switch (updateOperations) {
case UpdateOperations.Change:
// personChanging is the database version here, not the changed version.
break;
default:
break;
}
}
Here is my client-side code (jQuery):
var data = {
FirstName: "NewFN",
LastName: "NewLN"
};
$.ajax({
type: "PUT",
url: serviceUrl + "/People(" + personID + ")",
contentType: "application/json",
dataType: "json",
data: JSON.stringify(data),
success: function (data) {
alert("Success!");
},
error: function (error) {
alert("An error occured");
}
});
Here is the JSON being sent to the server:
Here is the ChangeInterceptor when the message is received:
I have uploaded the code for this project here: http://andyjmay.com/test/2921612/ODataTest.zip
I downloaded your sample , reproed your issue and was able to see the latest updated value using this work-around for now.
While I investigate this internally,Can you change your code to use a Merge verb instead of a PUT ?
With this change, you should now be able to see the latest entity values being passed in to the ChangeInterceptors when you update the values via the jQuery client.
$.ajax({
beforeSend: function (xhrObj) {
xhrObj.setRequestHeader("X-Http-Method", "MERGE");
},
type: "POST",
url: serviceUrl + "/People(" + personID + ")",
contentType: "application/json",
dataType: "json",
data: JSON.stringify(data),
success: function (data) {
GetAllPeople();
},
error: function (error) {
alert(error);
}
});
WCF got some nice extension you can write like MessageInspector and ParameterInspector.
I'm sure one of them can help you validate stuff before the server even starts to work with tthe request.
If the service is EF based and the request is PUT, then the old value will be provided (this has to do with the way the EF provider is implemented and might be a bug, we will look into that some more). You can workaround this by sending a MERGE request instead. I verified, that in that case it works as expected (you get the new values). MERGE has a little different semantics, but it might work for you. PUT overwrites the entity, so if you didn't send a value for a given property it will be reset to its default value. MERGE only modifies the existing entity with the values from the payload, so if some property is not in the payload its value will be left untouched.
Hmm... you say personChanging is the database version, it should definitely be the updated version.
My tests (and people on the product team) tell me it should be the version that came over the wire. Could something else be going wrong?
For example could your property be Firstname instead of FirstName?
Related
I am building a SPA ember.js app that will hit a .net API via an ajax call.
ember.js
getData: function(){
$.ajax({
type: "POST",
url: "http://localhost:9001/controller",
dataType : "json",
headers: "Access-Control-Allow-Origin",
contentType: 'application/json; charset=utf-8',
success : function(data) {
return data;
},
error:function(data){
alert('test' + data);
}
})
}
It returns an error message : SyntaxError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': 'function () { return _emberRuntimeSystemString.fmt(this, arguments); }' is not a valid HTTP header field value.
I have been hammering away at this issue for a few hours now and I just can't seem to get around it. Also very new to ember.js.
If anyone has a better idea of whats going on...
Well,
the problem is in your headers. You are not giving "Access-Control-Allow-Origin" a value.
So you want something like
headers: {"Access-Control-Allow-Origin": 'value' }
Also, I don't think that particular header is used that way? I believe it's a header that the server sends.
Check this post out - How does Access-Control-Allow-Origin header work?
Pav
C#
public ActionResult SimpleQuery()
{
ClientDataContext dc = new ClientDataContext();
var userResults = from u in dc.TS_Trucks select u;
return Json(userResults.ToList(), JsonRequestBehavior.AllowGet);
}
Javascript
$.ajax({
url: '#Url.Action("SimpleQuery")',
type: 'GET',
dataType: 'json',
success: function (data) {
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
});
I don't even use the data in the JavaScript, something about the way I'm passing it is probably the problem but can't seem to figure it out.
you need to specify the controller for your url helper. The server error is from trying to locate your action. Try this for the ajax url:
'#Url.Action("SimpleQuery", "<ControllerForYourActionHere>")'
Internal Error usually infers bad URL address.
In this case, url parameter is not set to right value.
First, you need to check which Router map to this function: SimpleQuery
Then, use that address to fill in url parameter.
Also, I don't think '#Url.Action("SimpleQuery", "<ControllerForYourActionHere>")' will work if you put
it in javascript file. It might works in cshtml file.
So, the conclusion is when you are doing frontend programming, use absolute link will be a good idea.
It make sure you hit the right address at the first time.
I am trying to learn how to program a web service with ServiceStack and call it via ajax in JavaScript. I did this by watching the pluralsight movies and I think I almost figured it out how to do that except for passing data as parameters with a service call.
I try to call the service with this ajax-call:
var request = { };
request.Amount = 32;
$.ajax({ type: 'POST',
contentType: 'application/jsonp; charset=utf-8',
url: "http://localhost:1879/entry",
dataType: 'jsonp',
data: {request: request},
success: function(result){
alert(result.Id);
}});
The service looks like this:
public class EntryService : Service
{
public object Post(Entry request)
{
return new EntryResponse() { Id = request.Amount };
}
}
[Route("/entry", "POST")]
public class Entry
{
public int Amount { get; set; }
}
public class EntryResponse
{
public int Id { get; set; }
}
I expect the alert in the callback to show the number 32, but it shows the number 0. And when I debug my service I see that request.Amount is 0 as well, so I think I do something wrong at the Ajax service call but I cannot figure out what. So I wonder what I am doing wrong here.
author of that Pluralsight course here. Hopefully I can help you.
First thing you should do is make sure the API is working correctly.
Go to this: http://localhost:1879/entry
In your web browser you should see a page displayed that has information about the service. If you don't your URL is wrong or ServiceStack is configured wrong.
Assuming the URL is correct, all you should need to do is wrap your data in JSON.Stringify().
When you do a post, the data has to be in JSON format as a JSON string. You are currently sending a JSON object.
Also, most likely you can drop the localhost bit off your url in the $.ajax call and just do "entry"
You can not do a post with JsonP. If you are trying to do a cross domain POST you need to look into cors and make sure that is enabled for the the service you are POSTing to.
Post data to JsonP
I only used jsonp cause I read and hoped that it could be the solution for my problem. But based on your explanation I shouldn't need it, so I changed my code to this:
var request = { };
request.Amount = 32;
$.ajax({ type: 'POST',
contentType: 'application/json; charset=utf-8',
url: "http://localhost:1879/json/reply/Entry",
dataType: 'json',
data: request,
success: function(result){
alert(result.Id);
},
error: function(xhr, ajaxOptions, thrownError){
alert("Failure!");
alert(xhr.status);
alert(thrownError);
}});
First I had this call without the error part and nothing happened, no alert, no error, nothing. So I assumed the error was consumed instead of being showed, so I added the error callback and my assumption seemed to be right. Now I get 3 alerts and the last 2 alerts shows "400" and "bad request".
I searched on those errors and tried but none of the possible solutions I found fixed my problem. I tried 2 urls: /json/reply/Entry and /entry after the localhost part but both didn't work. So what am I doing wrong?
I calling multiple function on page load in my asp.net web application.
All function run on page ready method
see the below code
$(document).ready(function(){
func1();
func2();
func3();
//.... so on.
});
function func1()
{
$.ajax({
type: "POST",
url: "Contents.asmx/GetText",
data: "{ }",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
/some code
}
});
}
function func2()
{
$.ajax({
type: "POST",
url: "Contents.asmx/GetTitles",
data: "{ }",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
/some code
}
});
}
.... like wise others
For backend I using SQL server-05.
When page is loading It getting more time to load,
above functions takes 30+ seconds to load.
How to optimze function calling?..
You could aggregate all the queries into a new web method which will perform all the SQL queries at once. Then send a single AJAX request to this new method. And as far as your SQL server is concerned you could also send multiple SQL queries into a single round-trip. Try optimizing the SQL queries as much as possible. Also you could cache the results of some expensive queries.
As long as /some code is not too much there is not really much you can do. These ajax calls area light-weight. Your problem is probably in the backend, where you send your requests to.
To debug/profile your problem, first check your ajax requests. Check them in a web-tool like Firebug and see that your request is expected. There you can also check which of your requests takes how long.
As you now see your bottleneck (e.g. requesting Contents.asmx/GetTitles is what takes so long), check your server that provides that page. As you did not provide code of that one, we can not help you there. But that’s where you have to look for next.
I have a table where the users are allowed to drag and drop rows in the order they want, and then save them. I have no problem with getting the drag and drop part to work. It's the saving I'm having issues with. I'm sending an Ajax call to a web service which will then make the save. I can't seem to actually catch the request in the web service though.
My JavaScript function looks like so:
$(document).ready(
function () {
$(".sortable").sortable({
update: function () {
serial = $('.sortable').sortable('serialize');
$.ajax({
url: "MyWebService.asmx/SortTable",
type: "post",
data: serial,
error: function () {
alert("theres an error with AJAX");
}
});
}
});
});
The JSON string looks fine from what Firebug is showing me. The web service function is like so:
[WebMethod]
public string SortTable(String[] rows)
{
//SaveChanges();
return "Called!";
}
When I put a breakpoint in there, it never gets hit. When there are no arguments in the function though, it will get hit. I've tried replacing "String[]" with "object" and it still doesn't get hit, which I find odd. What is going on here?
You might need to decorate your web service with the [ScriptService] attribute in order to allow client scripts to invoke it. Also if you are sending a JSON request you need to specify the content type. Another remark is about sending the request as an actual JSON object which could be achieved using the JSON.stringify method (maybe the $('.sortable').sortable('serialize') call already does this, I am not familiar, you just need to ensure that the POSTed value looks like this: [ 'row1', 'row2', ... ]):
$.ajax({
url: 'MyWebService.asmx/SortTable',
type: 'post',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify([ 'row1', 'row2', 'row3' ]),
error: function () {
alert('theres an error with AJAX');
}
});