I have built a ASP.Net Core 3.1 Web API, and I am interested in auto-generating documentation for my clients. I've followed the very simple instructions found here: Microsoft docs to install either NSwag or Swashbuckle in my project and in both cases I can see documentation for my APIs, but there are no descriptions on the model properties.
Java seems to have an #ApiModelProperty annotation for this, but I don't see a similar attribute in .Net. Is it possible to add descriptions for Model properties in either of these swagger implementations, that would show up in Schema section in the Swagger UI?
Standard xml doc summary works for me.
public class TokenRefreshRequest
{
/// <summary>
/// The JWT access token
/// </summary>
public string AccessToken { get; set; }
/// <summary>
/// The refresh token that was sent via the new token endpoint or the last refresh.
/// </summary>
public string RefreshToken { get; set; }
}
Shows on the swagger page as;
You can add limited markdown as well but I can't seem to find the link.
Related
guys:
I use swagger to make api document. I use ASP.NET WebAPI2 to develop WebAPI.
And I met three questions:
First: How could I Add Comments for the WebAPI Controller? I try to add Comment on Controller
namespace IMCAPI.Controllers
{
/// <summary>
/// Value API
/// </summary>
[Authorize]
public class ValuesController : ApiController
{
// GET api/values
/// <summary>
/// Get all Values
/// </summary>
/// <returns></returns>
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
, but not work.
Second:How could I search specific WebAPI in Swagger by brower Url? like this Browser Url Search
For example, if I want to search Value API, I input Value in the red section,I want the search result would just show Value API, I don't want other API appears(like Account). Or how to setting SwaggerConfig.cs that can have the search function?
Third:I want to know whether swagger could just read one xml file? I search the Internet, they demo like this
private static string GetXmlCommentsPath()
{
return String.Format("{0}/App_Data/IMCAPI.XML", AppDomain.CurrentDomain.BaseDirectory);
}
If I have multiple XML file, how could I integrate in the swagger?
that it. Hope somebody can help me. Thank you!
Your first question: The comments are appearing, you've put them on the Get method in your code, they're appearing on the Get method in your screenshot. If what you want is a description of the whole service, the Swagger documentation says to use the Description method.
Your second: You can't it shows all the methods on that API.
Third: The Swagger documentation says you call IncludeXmlComments multiple times with the path to each XML.
After reading some ServiceStack wiki, I have a problem about DTO and I was hoping you could help.
The wiki said:
In Service development your services DTOs provides your technology agnostic Service Layer which you want to keep clean and as 'dependency-free' as possible for maximum accessibility and potential re-use. Our recommendation is to keep your service DTOs in a separate largely dep-free assembly.
(https://github.com/ServiceStack/ServiceStack/wiki/New-API)
Finally you can also use the previous more explicit client API (ideal for when you don't have the IReturn<> marker):
(https://github.com/ServiceStack/ServiceStack/wiki/New-API)
According to the reasons above, I consider the best practice about ServiceStack is:
We should use POCO Request-Response DTOs instead of inheriting from IReturn<>.?
For instance:
We should use 1#:
public class AuthenticationRequest
{
public string Name { get; set; }
public string Password { get; set; }
}
public class AuthenticationResponse
{
public AuthenticationResponseType Result { get; set; }
public UserInfoDto UserInfo { get; set; }
}
We shouldn't use 2#:
using ServiceStack;
public class AuthenticationRequest : IReturn<AuthenticationResponse>
{
public string Name { get; set; }
public string Password { get; set; }
}
public class AuthenticationResponse
{
public AuthenticationResponseType Result { get; set; }
public UserInfoDto UserInfo { get; set; }
}
Because 1# is zero dependency, 2# have a dependency on ServiceStack library/framework.
If I package all Request-Response DTOs to a NET DLL, 1# is more abstract than 2#!
This means:
If one day in the future I deceide not to use ServiceStack, this DLL doesn't need any change. (ServiceStack library/framework should be Infrastructure not Abstraction)
Please correct me if I am wrong.
Very thanks.
The only dependency DTO's should have is the impl-free ServiceStack.Interfaces.dll which as it's a Portable Class Library (PCL) supports almost every mobile or Desktop platform that .NET runs on. ServiceStack's Interfaces .dll is required in order to be able to cleanly describe your complete Services contract in a single, benign .dll.
For example. the [Route] metadata attribute captures the Custom Routes where the remote Services are hosted which is required info about your Service that clients need to know in order to be able to call services via their published Custom Routes. Likewise the IReturn<T> interface marker provides a strong-typed contract on what your Service returns which is what enables ServiceStack succinct end-to-end Typed API. Essentially ServiceStack.Interfaces is a required extension to be able to capture your entire Service Contract in your Services DTO's.
ServiceStack.Interfaces can be used outside of ServiceStack
Even if you don't use ServiceStack, you can still use the benign ServiceStack.Interfaces.dll which the clients can introspect to find out more information about your DTO's and the remote Service Contract. Whilst I'm not seeing any reason to, if you want to decouple the ServiceStack.Interfaces on your project you can just copy the attributes you're using in your DTO .dll freeing it from any external dependencies. But this would impact your ability to have a generic Service Client since these embedded interfaces and attributes are unknown to your client library, limiting its ability to enable rich generic functionality using it.
Service Contract Interfaces and Attributes in other Languages
To support non .NET languages like TypeScript, ServiceStack emits these interfaces in the generated DTO's so they don't require any dependencies.
Likewise in Add ServiceStack Reference support of Swift 2.0 or Java and Android these additional contracts are emitted idiomatically referencing a Swift IReturn protocol or IReturn<T> interface in the Java android client package which is also what enables the succinct Typed API's ServiceStack enables on both iOS and Android.
Service Design
Something you should keep in mind when designing your API's is that your Service Layer is your most important contract. i.e. Your API exists to allow consumers access to your remote Servers capabilities, so your internal logic should be a hidden impl-detail, not something that should impact the external surface area of your API.
The Request DTO defines your Service Contract where I find using a Request suffix is an ugly construct that negatively affects the readability of your external API, e.g. Here's a typical example of what a noun with a *Request suffix would look like:
var response = client.Get(new CustomerRequest { ... });
Compared with using a Verb where the Request DTO is indicative and provides better readability of what the Service does:
var response = client.Get(new FindCustomers { ... });
Your Request DTO should ideally be a verb that's grouped by call semantics and Response Type. Having a *Dto suffix is an indication that your internal implementation is leaking and affecting the ideal Service Contract your external API Consumers will bind to (and should never change). Keep in mind the objective of your Service is to provide re-usable functionality to your consumers so your impl should realize your published contract, not the other way around where its implementation dictates what the contract should be.
With that in mind I would rewrite your ServiceStack Examples to look like:
public class Authenticate : IReturn<AuthenticateResponse>
{
public string UserName { get; set; }
public string Password { get; set; }
}
public class AuthenticateResponse
{
public AuthenticationResult Result { get; set; }
public UserInfo UserInfo { get; set; }
}
Which ends up being similar to ServiceStack's built-in Authenticate and AuthenticateResponse Request and Response DTOs.
I also recommend reading this earlier answer to understand the importance of DTO's and how it relates to the goals of a Service.
I am writing a Web API that clients can make requests to to return data in XML format. I am implementing this in .NET using Enterprise Foundation and MVC4.
I am struggling a bit with how to only return a subset of some fields from my Models in my Controllers.
For arguments sake, lets say I have a Product model that contains attributes "Id", "Name", "Price" and "Actual Cost" (I am using an example from http://www.asp.net/web-api/overview/creating-web-apis/using-web-api-with-entity-framework/using-web-api-with-entity-framework,-part-6)
I need to expose a Web API for clients to query a specific Product to get its name and price, but in this response I don't want to return the "Actual Cost" property (because this is our secret).
Now in the link I provide this is exactly the problem they are attempting to solve by the use of DTO's (they define a DTO called ProductDTO that contains only the subsets I want to return). I have implemented this solution and I am indeed now able to return only the fields I specify in the DTO.
The problem is that the naming used for the returned entity in XML is now ProductDTO rather than Product, i.e. the returned XML is
{"ProductDTO":[{"Id":1,"Name":"Tomato Soup","Price":1.39}, {"Id":3,"Name":"Yo yo","Price":6.99]}
rather than
{"Product":[{"Id":1,"Name":"Tomato Soup","Price":1.39}, {"Id":3,"Name":"Yo yo","Price":6.99]}
That means that all of our clients currently using our API and expects a "Product" to be returned will now get a "ProductDTO" returned, which means that they will have to make changes to their code and which is unacceptable. I need to provide them with a "Product" with only the relevant set of sub-fields as they are currently getting. How do I achieve this? I cannot simply "ignore" a data member as suggested in prevent property from being serialized in web api because I also have some API cases where I indeed DO need to return ALL the attributes and not only a subset.
Just some background: We have an existing API server interface that was written in Ruby on Rails and we are now moving this over to C# and .NET MVC4. We also have a bunch of client applications already interfacing to our existing, older, Ruby on Rails API Server and we don't want clients to make any changes to their code. We are simply moving our API server code over from Ruby on Rails to C#. In Ruby on Rails I was simply able to apply a filter to the XML Serializer when I need to only return a subset of attributes on certain calls.
If you want to continue down the DTO route that you have started, which IMHO is a good idea as it gives you control of what you export without polluting your internal classes with export specific stuff, you can add a DataContract attribute to your ProductDTO class.
[DataContract(Name="Product")]
public class ProductDTO
{
[DataMember]
public int Id {get;set;}
[DataMember]
public string Name {get;set;}
}
The default XML formatter used in Web API is the DataContractSerializer.
You can read more about this here
Suppose you have a class like
public class product
{
public string Name{get; set;}
..
}
and you don't want to appear it in the response you can just use [XMLIgnore] attribute
[XMLIgnore]
public string Name{get; set;}
hopes this helps.
With Data Annotations it's now easy to localize error messages using Resource.resx files like this for example:
public class Student
{
. . .
[Required(ErrorMessageResourceName ="Required",
ErrorMessageResourceType = typeof(StudentResources))]
[StringLength(16)]
[Display(Name = "FirstName", ResourceType = typeof(StudentResources))]
public string FirstName { get; set; }
. . .
}
Now, let's say I want to check if a Student has already made a Payment for a given month and year:
public bool CheckIfAlreadyPaid(Payment payment)
{
return repository.GetPayments().Any(p => p.StudentId == payment.StudentId &&
p.Month == payment.Month &&
p.Year == payment.Year);
}
If he has already made the Payment, I'm doing the following in my Services layer:
if (CheckIfAlreadyPaid(payment))
{
modelState.AddModelError("AlreadyPaid",
Resources.Views.Payment.PaymentCreateResources.AlreadyPaid);
}
It works, but I don't fell confident about referencing the Resource file inside the Services layer.
Is there a standard or better way of localizing error messages that are not tied to model properties (Data Annotation) - errors that come from business logic rules? Should I still add these errors to the ModelStateDictionary?
I agree, I don't think that should be in the service layer. It looks like it could either be put into a custom data validation attribute, or handled with some other approach at that level (using Fluent Validation might be a good option). Either way, I think as long as the validation stays in the MVC app itself, you can be comfortable using resource files to store the messages.
I did it in a different way. The Service layer is used to check if the Payment was already made. In my Controller I add a validation error message to the ModelState object passing to it a localized string resource. Now I feel more comfortable with this approach.
Here's the code:
/// <summary>
/// Performs validation of business logic...
/// </summary>
/// <param name="payment"></param>
/// <returns></returns>
private bool ValidatePayment(Payment payment)
{
if (paymentService.IsPaymentMade(payment))
{
ModelState.AddModelError("AlreadyPaid", Localization.AlreadyPaid);
}
return ModelState.IsValid;
}
EDIT:
To complement my answer, I just found today that ValidationSummary #Html.ValidationSummary(true) does exactly what I want:
Html.ValidationSummary returns an unordered list (ul element)
of validation messages that are in the ModelStateDictionary object and optionally displays only model model-level errors.
I'm passing true and it will only display model-level errors (non data annotation errors) in the summary just at the top of the page. This is great but only if it would work... :)
I was facing a problem where my custom error messages not tied to model properties weren't appearing when I set ValidationSummary(true). I then searched using Google and found this post. I tried his solution but it didn't work. I then searched a little bit more and found this link in Google Books (Pro ASP.NET MVC 2 Framework by Steven Sanderson).
I tried what is described there passing an empty string as key (string.Empty) and it did the job.
if(paymentService.IsPaymentMade(payment))
{
ModelState.AddModelError(string.Empty, Localization.PaymentAlreadyCreated);
}
I would like to use DataAnnotations for basic client and server-side validation of my MVC ViewModels. My ViewModel looks like this:
public class MyViewModel
{
public Client Client1 { get; set; }
public Client Client2 { get; set; }
public Product Product { get; set; }
}
So I would like to check that both client objects have a name and telephone number, the product object has a valid numeric price, etc.
The problem I have is that both Client and Product are proxy types generated by Visual Studio from a web service, so I can't directly add the annotation attributes to their required properties.
I've read about using the MetadataType attribute to specify the meta data in an alternative class (with duplicate properties), but in this case I can't even add that attribute to the Client and Product classes.
Or can I? In the Web References folder where my VS solution is saved, there is a folder for the web service namespace containing a file called Reference.cs, which contains the VS generated code for the proxy types.
If I add the metadata to the classes in here, will this work—or is messing about with the generated code a really bad idea? Or is there just a simpler, cleaner way to do this?
After a bit of hunting I found that this is actually remarkably simple—it was just a case of my not knowing exactly what to search for!
You don't actually need to add the MetadataType attribute to the original class definition: you can add it to an empty partial class of the same type (make sure your partial class is in the same namespace as the original type).
Then you just create a "buddy" class containing your validation rules as you would normally:
using System.ComponentModel.DataAnnotations;
namespace WebServiceNamespace
{
[MetadataType(typeof(ClientMetaData))]
public partial class Client
{
}
public class ClientMetaData
{
[Required(ErrorMessage = "Please enter a name")]
public string Name { get; set; }
[Required(ErrorMessage="Please enter a telephone Number")]
public string Telephone { get; set; }
}
}
This works perfectly with the standard Model Binding and requires no access to the original code for the type, so you can easily set up validation rules with DataAnnotations, even for types which aren't part of your code base.
Modifying the generated code would work, so long as you don't regenerate it and write over your modifications. Other than the chance of losing your work if someone generates the reference, there isn't a reason you can't add the metadata references to the proxy classes.
The other alternative is using custom validation, or create a model that you then map the fields to the proxy objects. Creating a model that isn't based on the Client object would be your safest method.
I think it would be cleaner to create a model and then map the fields using AutoMapper and/or Model Generator Helper ( http://modelhelper.codeplex.com/ ).