How to use resources instead of strings for swagger api annotations in servicestack - internationalization

I'd like to create servicestack api and use swagger for autoupdatable documentation. The problem is that I need this documentation to be i18n-azied, so the question is, is it possible to do in servicestack?

It's not natively supported but ServiceStack's SwaggerFeature does provide model and property filters that let you modify the returned swagger models, i.e. providing an opportunity to substitute the text in the returned models, e.g:
Plugins.Add(new SwaggerFeature {
ModelFilter = model => myLocalize(model),
ModelPropertyFilter = property => myLocalize(property)
});
Whilst it's not heavily used yet, ServiceStack's approach to localizing strings is to route text through to AppHost.ResolveLocalizedString() which can be overridden in your AppHost to change what string is returned.

Related

How does a Laravel controller method handle multiple Form Request parameters?

I am getting back to Laravel after several years and trying to understand how an already existing REST API coded in Laravel works. I can't understand how a particular controller method with multiple Form Request parameters works (or if it actually does).
The REST API was coded in Laravel 5.1. I've looked at the official documentation (both 5.1 and the latest) and tried to search the web and SO for related topics (e.g., "laravel controller multiple form requests", "laravel controller multiple type-hint requests", etc.), but I can't seem to find a clear explanation. Maybe I'm looking at it from a wrong angle.
public function store(ProductRequest $productRequest, PromoRequest $promoRequest)
{
// Validate product
$product = new Product($productRequest->all());
// Validate promo
if ($promoRequest->get('promo')) {
$promo = new Promo($promoRequest->get('promo'));
}
...
}
In most documentation, the controller would accept only one Request object. I did actually see some examples that have multiple Form Request parameters, but often they were recommended to use only one Form Request. But best practice aside, how does this code work? When this method is called, how does Laravel know how to split the Request into two separate Form Request classes?
Please feel free to let me know if and how I can explain my question more clearly.
you can write like this:
function example(Request $request) {
$productRequest = new ProductRequest($request->all());
$promoRequest = new PromoRequest($request->all());
}
but on validate you should change the way to this:
$data = $productRequest->validate($productRequest->rules());
another way that i test in laravel 8 is to add both form request object in methd parameters like :
function example(ProductRequest $productRequest,PromoRequest $promoRequest) {
$productRequest->validated();
$promoRequest->validated();
}
The Laravel service container is a powerful tool for managing class
dependencies and performing dependency injection. Dependency injection
is a fancy phrase that essentially means this: class dependencies are
"injected" into the class via the constructor or, in some cases,
"setter" methods.
You can read more about it here: https://laravel.com/docs/5.8/container
Edit: Additional question: Still, I can't understand how the HTTP request (which is only one) can be split into two different Request classes?
The HTTP request isn't split; it is merely sent through both classes.
Ex:
function example(Request $request) {
$productRequest = new ProductRequest($request);
$promoRequest = new PromoRequest($request);
}
Would be the same.

How can I support arbitrary querystring params? (explode modifier?)

My API allows users to filter a database table using query string params (ie. ?age=30&location=Philadelphia). These params are different for each database table. How can I express that in API Blueprint?
The API Blueprint spec says it supports the explode modifier. This RFC 6570 validator suggests the explode modifier could accomplish this via an object, ie.
/api{?filters*}
And passing
{ filters: { age: 30, location: 'Philadelphia' } }
(The validator linked above illustrates this a bit better)
Of course, I'm not sure how to express the above in API Blueprint. Is it possible?

Set default WebAPI formatter

We are using WebAPI to mimic the handling of a legacy system. As a result, we would like the default response formatter to be the XmlFormatter and not the JsonFormatter. The reason is that some of the existing calls to the service do not supply the Accept: HTTP header field.
I can achieve this by removing the JsonFormatter from the Formatters collection and then re-adding it, forcing it to be at the end of the chain.
This then result in the default format response using the XmlFormatter. Although it works, it just doesn't feel correct, and although I am moving Json to the back of the collection, there is no guarantee that the XmlFormatter is at the front of the collection.
Ideas/thoughts?
Just add formatters in the right order. If ASP.NET Web API finds two formatters for the same content type, it will pick the first one, so it is very important to add formatters in the right order.
//somewhere in Web Api config
config.Formatters.Clear();
config.Formatters.Add(new XmlMediaTypeFormatter());
config.Formatters.Add(new JsonMediaTypeFormatter());
So the default will be XML, the first formatter, but the API still supports JSON if the request asks for it (with appropriate HTTP header).
Finally, another different approach, is to use a custom IContentNegotiator. It will allow you to select the most appropriate MediaTypeFormatter for a given request.
//somewhere in Web Api config
config.Services.Replace(typeof(IContentNegotiator), new MyCustomContentNegotiator());
An example is available here.
This is returned to automatically serialise and return json when content type is json.
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
((DefaultContractResolver)config.Formatters.JsonFormatter.SerializerSettings.ContractResolver).IgnoreSerializableAttribute = true;

ASP.Net Web API Help Pages: Ignore certain properties

Is it possible to have the Help Page sample generator ignore certain properties of a particular type?
For example, we use the same DTO for object Request and Response messages, for both POST and PUT requests. When user is POSTing a model (creating a new record) they don't need to provide the ID field.
But once its created and we serialize the new record into the response body, the ID field is included and returned to the client.
So in the POST request sample, I don't want the ID field to be displayed because for post request it doesn't make sense.
But the POST response sample, I do want the ID field displayed...
I am aware that there is the ApiExplorerSettings attribute which can be applied to a Class or Method...but is there anything similar for a Property?
Something like this would be great:
public class MyDTO
{
[ApiExplorerSettings(IgnoreForRequestApi = true, IgnoreForResponseApi = false)]
public int Id { get; set; }
// Other properties omitted for brevity...
}
Using the following annotation I've successfully hidden a property from the generation!
[ApiExplorerSettings(IgnoreApi = true)]
No, there isn't a similar option for a property. HelpPage uses formatter instances configured on the application to serialize the samples and as you can imagine the formatters must not have this knowledge within themselves.
Regarding workarounds:
a. You could explicitly set the raw sample for a particular action's requestsample via the SetSampleRequest extension of HttpRequestMessage. You should be able to see some examples about this in the file at *Areas\HelpPage\App_Start\HelpPageConfig.cs*.
b. In the file Areas\HelpPage\SampleGeneration\HelpPageSampleGenerator.cs, there is a method called WriteSampleObjectUsingFormatter which uses the application's formatter instances to write the samples. Here you would need to create new formatter instances having similar settings as your normal application has(so that they reflect the exact serialization/deserialization semantics that your application would normally react to when actual requests are made) and then try to hide the properties which you want to. We want to create new instances because we do not want to disturb the normal functioning of the application.
Example: In case of Json, you could create a new Json formatter instance and provide a ContractResolver which can hide the properties. Check this link: http://james.newtonking.com/projects/json/help/html/ConditionalProperties.htm
In case of Xml, I am not sure how we can hide properties without using the IgnoreDataMember attribute and also being non-intrusive.
Currently I would prefer option 'a' as its comparatively a simple workaround than 'b'.
ASP.NET WEB API uses Json.NET for JSON and DataContarctSerailizer for XML formatting so if you add [JsonIgnore] annotations over properties that you do not want included in your serialization should work just fine.

Set default response type in WCF Web Api

I've a set of services hosted with WCF Web Api and I communicate with them in JSON from javascript. In most cases I'm okay modifying the accepts bit of the header to require a JSON response but there are some cases arising where I can't do this. This is due the the javascript framework that I'm using (Ext JS). For some things it only lets me specify a URL and not the proxy defaults such as headers.
This isn't an Ext JS question however. Web Api seems to default to returning XML, and I'd like to know whether it's possible to change this default so that it can return JSON instead. Thanks in advance!
A bit of experimentation seems to indicate that the order of the configured formatters matter (which is quite intuitive).
By default, when you create an instance of HttpConfiguration, its Formatters collection contains these formatters:
XmlMediaTypeFormatter
JsonValueMediaTypeFormatter
JsonMediaTypeFormatter
FormUrlEncodedMediaTypeFormatter
The reason why XML is the default formatting is because it's the first formatter. To make JSON the default value, you can reorder the collection to look like this:
JsonValueMediaTypeFormatter
JsonMediaTypeFormatter
XmlMediaTypeFormatter
FormUrlEncodedMediaTypeFormatter
Given an instance config of HttpConfiguration, here's one way to reorder the collection:
var jsonIndex = Math.Max(
config.Formatters.IndexOf(config.Formatters.JsonFormatter),
config.Formatters.IndexOf(config.Formatters.JsonValueFormatter));
var xmlIndex = config.Formatters.IndexOf(
config.Formatters.XmlFormatter);
config.Formatters.Insert(jsonIndex + 1, config.Formatters.XmlFormatter);
config.Formatters.RemoveAt(xmlIndex);
Whether or not this is supported I don't know, but it seems to work on WebApi 0.6.0.
I actually found a simple way of dealing with this. First make sure that the default JSON formatter is first. And then set its type to text/html. This will insure that the browser gets JSON even if it does not set the header. Nice aspect of the below is that you never have to remember to set the accept header in client code. It just works and always default to JSON.
var jsonformatter = config.Formatters.Where(t => t.GetType() == typeof(JsonMediaTypeFormatter)).FirstOrDefault());
config.Formatters.Remove(jsonformatter );
config.Formatters.Insert(0, jsonformatter);
config.Formatters[0].SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
You could use the a delegating channel as described here http://blog.alexonasp.net/post/2011/07/26/Look-Ma-I-can-handle-JSONP-(aka-Cross-Domain-JSON)-with-WCF-Web-API-and-jQuery!.aspx which maps URIs like http://myserver/myresource/1/json to http://myserver/myresource/1 and sets accept header to application/json.
The delegating channel is part of the ContactManager_Advanced sample when you're downloading WCF Web API from http://wcf.codeplex.com.
It is contained in the UriFormatExtensionMessageChannel.cs file.
Look at the global.asax.cs of the sample on how to get it running.
According to the code the WCF Web API will always default to the XmlFormatter if it is in the collection of usable formatters. If it isn't the JsonFormatter is used instead if this is present. There is also a DefaultFormatter property but that is internal so you can't set that. Maybe a useful feature request to add?

Resources