2

I got recommended in another thread that I should use ServiceClient when using a ServiceStack API.

I would like to create a template function that can post any type of objects like this:

public Post2<T>(object: T, url: string, httpOptions)
{
try
{
  var client = new JsonServiceClient(`${environment.apiEndpoint}` + url)
  client.headers = httpOptions;
  client.post<T>(object);

}
catch(e)
{

}

}

The problem is that it tells me that "argument of type T is not assignable to parameter of type IReturn.

typescript-ref http://techstacks.io generated the following DTO's (for this purpose)

// @Route("/Equipments", "POST")
export class CreateEquipment
{
    public name: string;
}

// @Route("/Equipments/{Name}", "GET")
export class GetEquipment implements IReturn<Equipment>
{
    public name: string;
    public createResponse() { return new Equipment(); }
    public getTypeName() { return 'GetEquipment'; }
 }

 // @Route("/Equipments", "GET")
 export class GetEquipments implements IReturn<Equipment[]>
{
    public createResponse() { return new Array<Equipment>(); }
    public getTypeName() { return 'GetEquipments'; }
}

// @Route("/Equipments/{Name}", "DELETE")
export class DeleteEquipment
{
    public name: string;
}

I tried to use the following code to create the Post request.

var request = new CreateEquipment();
request.name = equipment.name;
var client = new JsonServiceClient(environment.apiEndpoint);
var response = await client.post(request);

This gives an error in the VS17; argument of type 'CreateEquipment' is not assignable to parameter of type 'IReturn<{}>'.Property createResponse is missing in type'CreateEquipment'

Which I presume means that I am missing something in my ServiceModel

Atle Kristiansen
  • 707
  • 7
  • 28

1 Answers1

1

ServiceStack's TypeScript Service Client should only be constructed with the BaseUrl for where your ServiceStack Host is located, or if you don't specify an argument it will use / by default:

var client = new JsonServiceClient(environment.apiEndpoint);

You also need to use it with the TypeScript generated DTOs from your ServiceStack Service which you can generate by installing the @servicestack\cli npm util:

$ npm install -g @servicestack/cli

Then using it to generate your Server DTOs from the BaseUrl (should be the same as environment.apiEndpoint):

$ typescript-ref http://example.org

Then you can use it to send populated Request DTOs:

var request = new MyRequest();
var response = await client.post(request);

Note your ServiceStack Services should be annotated with the IReturn<T> (or IReturnVoid) interface marker specifying the Services Response DTO.

You can also make API Requests using URLs, but you'll need to specify the Response DTO Type it returns, e.g:

client.get<GetTechnologyResponse>("/technology", { Slug: "ServiceStack" }) 
mythz
  • 141,670
  • 29
  • 246
  • 390
  • 1
    I just have to say, even thought I am not supposed too, but that solution was really nice! Keep up the good work! – Atle Kristiansen Mar 17 '19 at 00:54
  • I spoke to early.. The solution is still really nice, but I get argument of type "CreateEquipment is not assignable to parameter of type IReturn property createResponse is missing in CreateEquipment" I presume that this means that I am missing something in the class on the server. – Atle Kristiansen Mar 17 '19 at 01:06
  • @AtleKristiansen please update your question with the generated DTOs, your client code and full error details – mythz Mar 17 '19 at 01:10
  • @AtleKristiansen your CreateEquipment Request DTO needs an `IReturn` interface marker, rerun your server then you can run `ts-ref` without any arguments to update your TypeScript DTOs. – mythz Mar 17 '19 at 01:21
  • Should I create a DTO for the IReturn? – Atle Kristiansen Mar 17 '19 at 01:29
  • @AtleKristiansen No it should be whatever Response DTO your Service is returning. – mythz Mar 17 '19 at 01:29
  • I see, I currently return two types HttpResult and HttpError (as per suggestion by you earlier) should I create a more general one? I.E public Equipment Equipment { get; set; } public ResponseStatus ResponseStatus { get; set; } – Atle Kristiansen Mar 17 '19 at 01:38
  • @AtleKristiansen it should be whatever the Response Body is, i.e. the response in `HttpResult`. It should never be `HttpResult` or `HttpError` - they're internal server decorator classes. If your Service doesn't return anything (i.e. just throws a HttpError) than you should use `IReturnVoid` instead of `IReturn`. – mythz Mar 17 '19 at 01:42
  • has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. – Atle Kristiansen Mar 17 '19 at 02:00
  • Should I disabled the credentials mode on the server? – Atle Kristiansen Mar 17 '19 at 02:14
  • 1
    @AtleKristiansen You need to [Enable CORS](https://docs.servicestack.net/corsfeature) which doesn’t sound like you can use a wildcard host so you’ll need to specify an origin whitelist, see docs for an example. This could potentially also be the cause of your Angular HTTP client issues. – mythz Mar 17 '19 at 02:14
  • I was able to post using the HTTP Client, but I will take a look at this tomorrow. Thanks for the great assist. – Atle Kristiansen Mar 17 '19 at 02:38
  • I added the whitelisting, but now I get "Request header field headers is not allowed by Access-Control-Allow-Headers in preflight response." Instead, is there some options by default in the JsonServiceClient? – Atle Kristiansen Mar 17 '19 at 13:05
  • @AtleKristiansen you have an issue with your CorsFeature configuration, do you have anything else in allowedHeaders besides Content-Type? – mythz Mar 17 '19 at 13:52
  • allowedHeaders: "Content-Type, Authorization". What more do I need? – Atle Kristiansen Mar 17 '19 at 15:23
  • @AtleKristiansen The `JsonServiceClient` only uses `Content-Type` by default or `Authorization` if you're using a BearerToken or Basic Auth, so there should be nothing else needed for the `JsonServiceClient`. It's not clear what header it's having an issue with, perhaps if you open a new question showing the full HTTP Request/Response headers being sent (using something like [Fiddler](https://www.telerik.com/fiddler)) – mythz Mar 17 '19 at 15:52
  • Done, I cannot see any data capture between the webservice and the API tho..https://stackoverflow.com/questions/55209512/cors-configuration-issues-when-using-servicestacks-jsonserviceclient – Atle Kristiansen Mar 17 '19 at 16:51