1

I am trying to build a service client to simplify calling my microservices in .net core.

Here is a service client sample:

    public ProductServiceClient(SystemEnvironment.MachineEnvironment? environment = null)
    {
        this.url = ServiceEnvironment.Urls.GetUrl(ServiceEnvironment.Service.Product, environment);
    }

    private RestClient GetClient(string method)
    {
        return new RestClient(url + "/api/" + method);
    }

    private RestRequest GetRestRequest(Method method)
    {
        var restRequest = new RestRequest(method);

        restRequest.RequestFormat = DataFormat.Json;
        restRequest.AddHeader("Content-Type", "application/json");

        return restRequest;
    }

    public FindProductsResponse FindProducts(FindProductsRequest request)
    {
        var restRequest = GetRestRequest(Method.GET);

        restRequest.AddJsonBody(request);

        var client = this.GetClient("Products");

        var restResponse = client.Get(restRequest);

        return new JsonDeserializer().Deserialize<FindProductsResponse>(restResponse);

    }

    public void Dispose()
    {
    }

And here is how I am trying to read it in my .net core api:

    [HttpGet]
    public ActionResult<FindProductsResponse> Get()
    {
        var request = "";
        using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
        {
            request = reader.ReadToEnd();
        }

        var buildRequest = JsonConvert.DeserializeObject<FindProductsRequest>(request);


        var products = _service.FindProducts(buildRequest);

        if (products != null && products.Any())
        {
            return new FindProductsResponse()
            {
                Products = products
            };
        }

        return BadRequest("Not found");
    }

However the request variable is always empty after Request.Body has been processed by the StreamReader.

If I make the same request from Postman (also using GET), I get the body just fine. What am I doing wrong here?

EDIT: This is the unit test calling the api:

    [Test]
    public void Test1()
    {
        using (var productServiceClient = new ProductServiceClient())
        {
            var products = productServiceClient.FindProducts(new FindProductsRequest()
            {
                Id = 50
            }).Products;
        }
    }

2 Answers 2

0

It can be your Request.Body has been already consumed. Try to call Request.EnableRewind() before to open the StreamReader.

Sign up to request clarification or add additional context in comments.

5 Comments

Didn't change anything :-( I'm really confused, since it works through postman.
And how do you notice the error? A unit test? A console app who call the api?
Unit test - I run a spike from another project, that calls into the api using the service client that I've built. Is it because of RestSharp being unable to attach a body to a GET request, whilst Postman being able to? I tried copying the code from postman (apparently, it can generate C# RestSharp code, which is pretty neat) and pasting it directly into my client. Same headers, same everything, still no body though. I'm starting to reach the point where I change it to a POST operation instead, however GET would be optimal in this case.
Sure, it's really basic though. Edited my original post
In your code you create a rest request with method GET and you tried to attach it a body. In a GET request you can't add body. Not even from Postman! If you need to pass a body you can't use GET method, but POST or PUT. If you want a GET, you should pass parameters in query string.
0

I'm not sure why you are manually doing it. It looks like you are reinventing the wheel. ASP.NET Core already does that for you.

This is what your service should look like:

[HttpGet] // oops, GET requests will not allow Bodies, this won't work
public ActionResult<FindProductsResponse> Get([FromBody]FindProductsRequest buildRequest)
{
    // skip all the serialization stuff, the framework does that for you

    var products = _service.FindProducts(buildRequest);

    if (products != null && products.Any())
    {
        return new FindProductsResponse()
        {
            Products = products
        };
    }

    return BadRequest("Not found");
}

And if you don't want to redo all the busy work that is retyping all the code on the client side, I suggest you read up on swagger (probably in the form of Swashbuckle). Client code can be generated. Even from within Visual Studio, if you right-click on the project and in the context menu pick "Add REST API Client...". Please don't erroneously hand-code what can be generated flawlessly by a machine instead. I don't really know what went wrong in your specific case, but searching bugs that could be avoided altogether is just busywork, that time should be spent on other parts of the program.


I just realized this is a GET request. ASP.NET will not recognize bodies for GET-Requests. You will need to make it a PUT or POST request or put your parameters in the query string.

If you happen to make that mistake as often as I did, you might want to write some unit tests that cover this. Because .NET is not helping you there. Been there, done that..

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.