简体   繁体   中英

How do I use Swagger with dynamic parameters from a Web API Action Method?

I write my Web API controllers in a non-standard way where I get the parameters as dynamic objects.

This creates an issue with NSwag. Because there are no parameters in the method definition, NSwag cannot generate what is needed.

I wonder if there is any option to use NSwag in this situation. Maybe there are some attributes that I can add to the methods so that NSwag will be able to generate the API?

[HttpPost]
[ActionName("create-account")]
public IHttpActionResult CreateAccount()
{
    var body = Request.Content.ReadAsStringAsync().Result;

    dynamic json = Utils.GetJsonBody(body);

    if (!Utils.GetJsonPropertyValueByPropertyName<String>(json, "email", out String email))
    {
        return Content(HttpStatusCode.BadRequest, "Please provide a valid email.".AsApiMessageResult());
    }

    if (!Utils.GetJsonPropertyValueByPropertyName<String>(json, "name", out String name))
    {
        return Content(HttpStatusCode.BadRequest, "Please provide an account name.".AsApiMessageResult());
    }

    if (!Utils.GetJsonPropertyValueByPropertyName<String>(json, "domain", out String domain))
    {
        return Content(HttpStatusCode.BadRequest, "Please provide a valid domain.".AsApiMessageResult());
    } 

The thing about Swagger is that it uses the signatures of your method to generate its documentation of how your code works. Bypassing all the normal Web API and choosing to read the raw HTTP request means that Swagger can't see what you're doing, making it difficult for it to automatically determine what your code does. The technique you're doing with reading the raw request and using dynamic has a number of other disadvantages.

  • You don't get Intellisense for your objects
  • It's not functional meaning it's harder to tell by looking at the method what it takes as input and output, which makes it harder to understand
  • It's harder to unit test your code, because now you have to build up an HTTP request for your Web API controller
  • It requires more code than doing things with proper objects

Instead, we should define a proper model to post to our API. This will allow Web API to do its job, the model binder will handle converting the request into an instance of CreateAccountRequest.

public class CreateAccountRequest
{
    public string Email { get; set; }

    public string Name { get; set; }

    public string Domain { get; set; }
}

Then we can have our action method take this an instance of this class as a parameter.

[HttpPost]
[ActionName("create-account")]
public IHttpActionResult CreateAccount(CreateAccountRequest request)
{
    //now here you can validate the request if you want
}

Swagger should be able to understand this method now, allowing NSwag to generate a useful client.

Note that instead of doing custom C# validation, you should look into the built in tools that Web API provides for model validation . Then all you would need to do is check the ModelState, rather than manually checking each parameter. Other tooling can also look at the attributes of your models, enhancing the tooling experience.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM