total n00b when it comes to restful stuff, ajax, and so forth so please be gentle.
I have an issue whereby I have taken the example ServiceStack "Todo" service, and am trying to develop a mobile client using this service as a data source. I'm trying to learn how it all works so I can build a specific service which I feel SS is more suited to as opposed to WCF/WebAPI.
Anyway let's say that the Service is running on http://localhost:1234/api/todos
I have enabled CORS support based on cobbling together information found in various other posts.
So my Configure function looks like this:
Plugins.Add(new CorsFeature());
this.RequestFilters.Add((httpReq, httpRes, requestDto) =>
{
httpRes.AddHeader("Access-Control-Allow-Origin", "*");
//Handles Request and closes Responses after emitting global HTTP Headers
if (httpReq.HttpMethod == "OPTIONS")
{
httpRes.AddHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
httpRes.AddHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type");
httpRes.StatusCode = 204;
httpRes.End();
}
});
and I have a service method like this on the TodoService:
[EnableCors]
public object Post(Todo todo)
{
var t = Repository.Store(todo);
return t;
}
Using a browser (FF/IE) If I call this ajax function:
var todo = { content: "this is a test" };
$.ajax(
{
type: "POST",
contentType: "application/json",
data: JSON.stringify(todo),
timeout:20000,
url: "http://localhost:1234/api/todos",
success: function (e) {
alert("added");
app.navigate("Todo");
},
error: function (x, a, t) {
alert("Error");
console.log(x);
console.log(a);
console.log(t);
}
}
);
from http://localhost:1234, then it all works fine. The todo gets added and in the success function, "e" contains the returned todo object the service created.
However, if I call this from anywhere else (http://localhost:9999 i.e the asp.net dev server that the mobile client app is running under) then, although the Service method executes, and the todo does get added on the server side, the response back to jquery is empty, and it hits the error function right away.
I'm convinced I am doing something dumb but I can't for the life of me see it. Anyone have any clue? Thanks in advance...
Update: Well it seems to work OK now, the problem appeared to be
httpRes.AddHeader("Access-Control-Allow-Origin", "*");
outside of the "OPTIONS" block. So the code that works in apphost is
Plugins.Add(new CorsFeature());
this.RequestFilters.Add((httpReq, httpRes, requestDto) =>
{
//Handles Request and closes Responses after emitting global HTTP Headers
if (httpReq.HttpMethod == "OPTIONS")
{
httpRes.AddHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
httpRes.AddHeader("Access-Control-Allow-Origin", "*");
httpRes.AddHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type");
httpRes.StatusCode = 204;
httpRes.End();
}
});
so it turns out there was a problem in my original code; the amdended code is:
Plugins.Add(new CorsFeature());
this.RequestFilters.Add((httpReq, httpRes, requestDto) =>
{
//Handles Request and closes Responses after emitting global HTTP Headers
if (httpReq.HttpMethod == "OPTIONS")
{
httpRes.AddHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
//this line used to be outside the if block so was added to every header twice.
httpRes.AddHeader("Access-Control-Allow-Origin", "*");
httpRes.AddHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type");
httpRes.StatusCode = 204;
httpRes.End();
}
});
So the CorsFeature() plugin would appear to be correctly handling all CORs stuff for POST, GET and the pre-flight OPTIONS request is being handled by the RequestFilter (confusion - why doesn't the plugin just handle the OPTIONS request?) ; in the old code, the allow-origin header was being added twice for every request (by the plugin and by the filter) and this seems to have been confusing either jquery or the browser.
Not that I fully understand any of this , I have some reading to do :) and it's all been rendered moot anyway since the mobile framework I am using (DXTreme) can't seem to handle anything other than JSONP (no good for me since I need POST/PUT) for a cross-domain Rest Data source, so I am already going to have to go the proxy route, or dump the framework, or find some other way around my issues.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With