1
votes

I can call my service using "/api/X" path via Javascript. (POST verb)

I can call same service without request object using client.Get(serviceUrl) //client is JsonServiceClient

But client.Send(X) does not work. I'm getting weird 404 NotFound response?

Am I missing something? And how can I debug problem?

The cost is 5 hours till now!

CheckList

  • X class have two string property (No enum or customType)
  • X and XResponse has DataContract and DataMember attributes (Trial)

Code:

In AppHost.cs

    base.SetConfig(new EndpointHostConfig
        {
            GlobalResponseHeaders =
                {
                    { "Access-Control-Allow-Origin", "*" },
                    { "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" },
                },
            AppendUtf8CharsetOnContentTypes = new HashSet<string> { ContentType.Html },
            DebugMode = true, //Show StackTraces in service responses during development
            LogFactory = new ElmahLogFactory(new Log4NetFactory())
        });

        //Set JSON web services to return idiomatic JSON camelCase properties
        ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;

        //Configure User Defined REST Paths
        Routes.Add<JobRequest>("/job");

In Model.cs

  [DataContract]
public class JobRequest : IReturn<JobRequestResponse>
{
    [DataMember]
    public string JobRequestEnum { get; set; }
    [DataMember]
    public string JobData { get; set; }
}

[DataContract]
public class JobRequestResponse : IHasResponseStatus
{
    [DataMember]
    public string Message { get; set; }

    [DataMember]
    public ResponseStatus ResponseStatus { get; set; }
}

In JobService.cs

 public class JobService : ServiceStack.ServiceInterface.Service
{
    public JobRepository Repository { get; set; }

    public object Any(JobRequest request)
    {
        return new JobRequestResponse() { Message = "ok" };
    }
}

In Javascript.js // IT WORKS

$.ajax({
type: 'POST',
url: "/api/job",
data: '{ "jobRequestEnum": "test", "jobData": "test" }',
dataType: "json",
contentType: "application/json",
success: function (res) {
    debugger;
}

});

In CallJob.js // IT DOES NOT WORK

string serviceUrl = ConfigurationManager.AppSettings["serviceUrl"];

        using (JsonServiceClient client = new JsonServiceClient(serviceUrl))
        {
            var request = new JobRequest() { JobData = "test", JobRequestEnum = "test" };
            var response = client.Send<JobRequestResponse>(request);
        }
1
Note: Your questions have a habit of being abrasive and lacking contextual information which are 2 characteristics less likely to attract any answers. i.e. You haven't provided the route definitions, nor the C# code you're using, nor the Service example (i.e. is it old or new API?). You also don't mention if HTTP POST works in JS or refs to docs on why you're assuming things should work. If you really spent 5 hrs on this? you should've noticed that client.Send() uses POST to the pre-defined routes which uses Request DTO name and has nothing to do with your custom routes.mythz
I'm not narcist @mythz :) and I respect your and other's work. I'm writing my answer if any of others is not exactly true. (Choosing one of the response is easier than writing fresh one. I'm using this for community.) But I promote all helpful responses! So this is not contest for me.ozz
The problem is your questions are usually lacking in info, so most answers are best efforts. If an answer helped you find your solution than the most helpful netiquette would be to mark the answer that was most helpful and edit your question to include the solution you've found. What you were doing before just discourages others to help, which is why I usually skip over your questions.mythz
Sorry for this. I misunderstood concept maybe. I did not mix question and answer.(IMHO it was better) But if you say this is better I will choose one of them as accepted and write my answer in a question after now :)ozz

1 Answers

2
votes

If you add the [Route] on your Request DTO like:

[Route("/job")]
[DataContract]
public class JobRequest : IReturn<JobRequestResponse>
{
    [DataMember]
    public string JobRequestEnum { get; set; }
    [DataMember]
    public string JobData { get; set; }
}

The new IReturn C# Client APIs

Then the C# Client will be able to use the custom /job route on the client, e.g:

var client = new JsonServiceClient(serviceUrl);
var request = new JobRequest { JobData = "test", JobRequestEnum = "test" };
JobRequestResponse response = client.Post(request);

Whenever you don't have the Route defined on the Request DTO or specify the Response type, e.g:

var response = client.Send<JobRequestResponse>(request);

You're not using the IReturn<T> C# client API so it will send a POST to the pre-defined route which for this would be:

POST /json/syncreply/JobsRequest
{ ... }

Not /jobs as you're assuming (i.e. the C# client has no way to know of the route info, so it falls back to using the pre-defined routes).

Manually specifying to use the /customroute

Otherwise if you want to keep your Route definitions in AppHost you can force it to use the pre-defined url by supplying it in the C# call, e.g:

client.Post<JobRequestResponse>("/job", request);

No need for 'Response' suffix

Also in the new API (and when you use the IReturn<T> marker) you no longer need the Request DTO + 'Response' naming convention and are free to choose any name you need, so it doesn't have to be JobRequestResponse which sounds a little awkward :)