Is there any way to provide multiple NSwag.Annotations.SwaggerResponse types for the same status code in Asp.net WebApi (not core)? Actually, I have two response types, both descendants of the same abstract class.
I have tried to specify the base class as the response type, which results in having that class in the generated descriptor as the response model. Which is kinda normal.
I have tried to add two attribute instances with the two descendants. The resulting model is still the base class, not the actual class specified, but the descriptions are merged.
[SwaggerResponse(HttpStatusCode.OK, typeof(DeliveryData), Description = "Provided PIN code belongs to a delivery")]
[SwaggerResponse(HttpStatusCode.OK, typeof(AdhocData), Description = "Provided PIN code belongs to an adhoc visitor")]
The result is:
Interestingly, in the model list, I see both the base class and the two descendants.
Is there any way to instruct NSwag to generate alternate models (oneOf)?
This page describes how to set up inheritance in the serializer and spec:
https://github.com/RicoSuter/NJsonSchema/wiki/Inheritance
Related
In my use case I have a RAML 1.0 library created by our R&D department that contains definition of multiple data types. Those data types are defined in a generic, parametrized manner so when I reference them in my RAML I do so using following syntax:
type: { resourceTypes.collectionWithCriteria: {itemName: reward, itemCriteria: types.RewardCriteria, itemType : types.RewardList} }
This generates proper GET request with query string defined by types.RewardCriteria and response defined by types.RewardList. It also generates the description for the GET resource defined as: Retrieves the list of <<itemName | !pluralize>>, which ends up being Retrieves the list of rewards.
In my RAML I would like to append additional description to my GET resource, however I 'd rather avoid overwriting library-generated one. Is that possible? I've already tried inline description and using overlay file, both of which simply replace description from the library.
You cannot append for a single value simple property.
The merging rules for traits / resource types state that the description will be replaced:
Every explicit node wins over the ones that are declared in a resource
type or trait. The rest are simply merged.
Also, the merging rules of overlays and extensions states that:.
If the property is a Simple Property
If the property is a Single-value Simple Property,
The property value in the identically named Current Target Tree Object property is replaced with its value from Current Extension Tree Object property.
Lets say we have a class "Car" than has different pieces of data ( maker, model, color, fabrication date, registration date, etc). The class has no method to get data, but it knows to as for it from another object (sent via constructor, let's cal it for short DS).- and the same for when needing to update changes.
A method getColor() would be implemented like this
if(! this->loaded('color')){
this->askDS('color') // this will do the necesarry work to generate a request to DS
}
return this->information('color');
Nothing too fancy so far. No comes the part i want to find out if it has a name, or if there are libraries / frameworks that do this already.
DS has a list of methods registered dinamically based on the class that needs data. For car we have:
input: car serial number, output: method to use to read the numbers to extract raw values
input: car raw color value, output: color code
input: car color code, manufacturer, year, mode, output:human-readable color (for example navy blue)
Now, DS or any method does not have an ordered list of using command to start from serial number and return the color blue, but if can construct a chain of methods that from one set of data, it can run them in order and get the desired data.
For our example above, DS runs 1,2,3 in that order and injects the data resulted from all methods into the class object that needed it.
Now if the car needs registration info, we have method (4) that gets that from the police database with an api request.
So, given:
- a type of model (class/object)
- a list of methods that take a fixed list of input(object properties) and give out a fixed list of output (object properties)
- a class DS that can glue the methods and run the needed ones for a model to get from property A (serial) to properby B (human readable colour) without the model or DS having a preconfigured way to get this data but finding it as needed.
does this have a name or is it already implemented somewhere ?
I've implemented a very basic prototype and it works very nice and i think this implementation method has useful features:
if you have a set of methods that do sql queries and then your app switches to using an api, you only need to change the methods and don't have to touch any other part of the application
when looking for a chain of methods that resolve the 'need' the object has, you can find a method chain, run it, if it fails keep looking for another list of methods based on the currently available data - so if you have multiple sources for a piece of data, it can try multiple versions
starting from the above paragraph i could start with an app that only has sql queries for data retrieval - when i find out a part of the app overloads the sql server i could add a method to retrieve data from cache with a lower cost than the one from database (or multiple layered caches, each with different costs)
i could probably add business logi in the mix the same ways as cache, and based on the user location / options present different data
this requires less coding overall, and decouples the data source from the object, making each piece easier to mock/test
what is needed to make this fast is a caching solution for the discovered method chains, since matching hundreds of thousands of methods per model type would be time-consuming but I don't think this is very hard to do - just store all found chains in memory as you find them and some metadata to be able to resume a search from any point in time - when you update the methods, just clear the cache, take a performance hit for the first requests
Thank you for your time
What you describe sounds like a somewhat roundabout way of doing Dependency Injection. Quote:
"Passing the service to the client, rather than allowing a client to
build or find the service, is the fundamental requirement of the
pattern."
Depending on what language you're using, there should be several Dependency Injection frameworks/libraries available.
Let's say I have a very simple ModelViewSet with a ModelSerializer that has a SerializerMethodField that is slow to compute.
class RasterViewSet(ModelViewSet):
model = Raster
serializer_class = RasterSerializer
class RasterSerializer(ModelSerializer):
...fields...
computed_info = SerializerMethodField()
class Meta:
model = Raster
fields = (...)
def get_computed_info(self, object):
# Lots of computation here.
Now my problem is that on the list page (mapped to say /api/rasters/), get_computed_info is called for all rasters.
I want the detail page to have the most essential fields for each raster, and the detail page for each raster to have all the available fields, including the slow ones.
It seems a very common pattern to me, to show only a subset of the detail fields on the list page, but I find it hard to search for a solution.
What's the best way to do this?
The way that this can be done is by using two different serializers: one for the list view, and one for the detail view.
You can control what serializer is used on a view by overriding get_serializer_class and returning a different serializer depending on certain conditions. In your case, you probably want to test view.action to see if it is create (POST on a list) or list (GET on a list) and only return the list serializer in that case.
Alternatively you can use the DetailSerializerMixin provided by drf-extensions, which packages this functionality into a mixin that can be used on your viewset.
I would like to determine whether an entity property is required or not.
Does anyone know how to access all of the constraints for a given entity property?
I want to check if the NotBlank constraint is active for a certain propery.
information:
You can check the mapping information for a class (or object) with the help of the service:
validator.mapping.class_metadata_factory
The underlying class is:
Symfony\Component\Validator\Mapping\ClassMetadataFactory
The service provides a method getMetadataFor() that allows you to obtain the active mapping metadata for a class (or object).
This method returns an instance of...
Symfony\Component\Validator\Mapping\ClassMetadata
... that provides a getPropertyMetadata(string $property) method that returns the Metadata for a given property name.
example usage:
Inside a controller (or any other ContainerAware instance) you can do:
$factory = $this->container->get('validator.mapping.class_metadata_factory');
$classMetadata = $factory->getMetadataFor('Your\Bundle\Entity\Name');
$propertyMetadata = $classMetadata->getPropertyMetadata('propertyName');
View the list of Supported Validation Constraints Reference from Symfony web site
You can try ladybug bundle. It is very easy to use and shows in detail and nicely to see all properties and info inside an object.
I'm using ASP.NET MVC3 and i'm wondering that the default modelbinder binds to public properties but not to public fields.
Normally i just define the model classes with properties but sometimes i use some predefined classes which contains some fields. And everytime i have to debug and remember that the modelbinder just don't like fields.
The question: Whats the reason behind it?
but sometimes i use some predefined classes which contains some fields
While I cannot answer your question about the exact reason why the default model binder works only with properties (my guess is that it respects better encapsulation this way and avoids modifying internal state of the object which is what fields represent) I can say that what you call predefined classes should normally be view models. You should always use view models to and from your controller actions. Those view models are classes that are specifically defined to meet the requirements of the given view.
So back to the main point: fields are supposed to be modified only from within the given class. They should not be accessed directly from the outside. They represent and hold internal state of the class. Properties on the other hand is what should be exposed to the outside world. Imagine that in the property getter/setter you had some custom logic. By modifying directly the field this custom logic would be broken and potentially bring the object into an inconsistent state.
Maybe the reason for ignoring fields is to increase performance of the binder. Instead of searching all the Fields and properties. The Model Binder search for Properties only.
Though I think the Model Binder use cache to improve performance.
DefaultModelBinder exposes a public method:
DefaultModelBinder.BindModel, and a number of protected method available for overriding. All of them listed here.
Besides the model, these method refer to properties only, not fields, like
GetModelProperties,
GetFilteredModelProperties,
GetPropertyValue,
OnXYZValidating,
OnXYZValidated,
OnXYZUpdating,
OnXYZUpdated,
GetXYZValue,
where XYZ stands for either Model, or Property/ies, or both, and so on.
As you can see there is no Fields mentioned with these names whatsoever. As Darin explained no direct changes to Model's state are tolerated by the Binder. Hence no Field in its methods.
And also, you may wish to take a look at another important class: ModelBindingContext. An instance of this class gets passed to the BindModel, and subsequently to BindSimpleModel, and BindComplexModel, depending on model type (string, int,... are considered simple, everything else is complex).
So, this context has the following properties:
ModelXYZ, and
PropertyXYZ.
In other words you have no means to reference the fields in your ViewModel unless you do not override these classes and undertake special actions to do so.
But again, beware of fighting the framework, its always easier to follow it instead.
EDIT: The ModelMetadata class holds all the data needed to bind the model. Its code however, shows no sign of fields, field names, etc. Only properties are referenced and accessed. So, even if you try to inherit and override DefaultModelBinder and ModelBinderContext, you still won't be able to access fiellds, nevermind what their access modifier is: public, private, etc.
Hope this explains most of it.