Specifying properties returned from API in client - asp.net-core

I want to limit the amount of properties that are returned from my REST api built in dotnet core. When accessing resources the client only needs specific subsets of the data returned from the api. What is a good way to tell the api which properties the client wants returned?
My initial thought would be to add query parameters to the endpoint like this:
http://www.restapi.com/v1/resource?fields=id,name,type
But I am not sure the best way to implement this in the api so that it is reusable and clean.

You're right that you usually don't want to return your full domain model or data model over your web API. Usually you define a custom model type for this purpose, which you can also decorate with attributes for model binding and model validation, if desired.
If you want the client to be able to determine what properties it gets, you can return an anonymous type built for this purpose, or perhaps have several DTO types predefined that the client's parameters result in.

Related

How to convert a LinqExpression into OData query URI

There are a lot of answers on how to convert ODataQuery into an Expression or into a Lambda, but what I need is quite the opposite, how to get from a Linq Expression the OData query string.
Basically what I want is to transcend the query to another service. For example, having 2 services, where your first service is not persisting anything and your second service is the one that will return the data from a database. Service1 sends the same odata request to Service2 and it can add more parameters to the original odata request to Service2
What I would like:
public IActionResult GetWeatherForecast([FromServices] IWeatherForcastService weatherForcastService)
{
//IQueryable here
var summaries = weatherForcastService.GetSummariesIQ();
var url = OdataMagicHelper.ConvertToUri(summaries);
var data = RestClient2.Get(url);
return data;
}
OP Clarified the request: generate OData query URLs from within the API itself.
Usually, the queries are so specific or simple, that it's not really necessary to try and generate OData urls from within the service, the whole point of the service configuration is to publish how the client could call anything, so it's a little bit redundant or counter-intuitive to return complex resource query URLs from within the service itself.
We can use Simple.OData.Client to build OData urls:
If the URL that we want to generate is:
{service2}/api/v1/weather_forecast?$select=Description
Then you could use Simple.OData.Client:
string service2Url = "http://localhost:11111/api/v1/";
var client = new ODataClient(service2Url);
var url = await client.For("weather_forecast")
.Select("Description")
.GetCommandTextAsync();
Background, for client-side solutions
If your OData service is a client for another OData Service, then this advice is still relevant
For full linq support you should be using OData Connected Services or Simple.OData.Client. You could roll your own, or use other derivatives of these two but why go to all that effort to re-create another wheel.
One of the main drivers for a OData Standard Compliant API is that the meta data is published in a standard format that clients can inspect and can generate consistent code and or dynamic queries to interact with the service.
How to choose:
Simple.OData.Client provides a lightweight framework for dynamically querying and submitting data to OData APIs. If you already have classes that model the structure of the API then you can use typed linq style query syntax, if you do not have a strongly typed model but you do know the structure of the API, then you can use either the untyped or dynamic expression syntax to query the API.
If you do not need full compile-time validation of your queries or you already have the classes that represent the resources served by the API then this is a simple enough interface to use.
This library is perfect for use inside your API logic if you have need of generating complex URLs in a strongly typed style of code without trying to generate a context to manage the connectivity to the server.
NOTE: Simple.OData.Client is sometimes less practical when developing against a large API that is rapidly evolving or that does not have a strict versioned route policy. If the API changes you will need to diligently refactor your code to match and will have to rely on extensive regression testing.
OData Connected Services follows a pattern where some or all of the API is modelled in the client with strongly typed client side proxy interfaces. These are POCO classes that have the structure necessary to send to and receive data from the server.
The major benefit to this method is that the POCO structures, requests and responses are validated against the schema of the API. This effectively gives you full intellisense support for the API and allows you to explor it's structure, the generated code becomes your documentation. It also gives you compile time checking and runtime safety.
The general development workflow after the API is deployed or updated is:
Download the $metadata document
Select the Operations and Types from the API that you want to model
Generate classes to represent the selected DTO Types as defined in the document, so all the inputs and outputs.
Now you can start using the code.
In VS 2022/19/17 the Connected Services interface provides a simple wizard for establishing the initial connection and for updating (or re-generating) when you need to.
The OData Connected Service or other client side proxy generation pattern suits projects under these criteria:
The API definition is relatively stable
The API definition is in a state of flux
You consume many endpoints
You don't want to manually code the types to serialize or deserialze payloads
Full disclosure, I prefer the connected service approach, but I have my own generation scripts. However if you are trying to generate OData query urls from inside your API, its not really an option, it creates a messy recursive dependency... just don't go there.
Connected services is the low-(manual)-code and lazy approach that is perfect for a stable API, generate once and never do it again. But the Connected Service architecture is perfect for a rapidly changing API because it will manage the minute changes to the classes for you, you just need to update your client side proxy classes more frequently.

SAP Gateway: How do setup a service to access an ABAP function directly, without any entities?

I'm putting together a SAPUI5 app which redirects to a 3rd Party site using an authentication token.
The token is generated in an ABAP function on the backend, so how do I call this directly via a SAP Gateway service without any structures or entities, as they aren't required.
I do however need a couple of return values passed back from the ABAP function through the Gateway service, so is this possible?
how do I call this directly via a SAP Gateway service without any
structures or entities, as they aren't required.
This isn't currently possible so I'm afraid implementing an entity or structure is required.
If you don't want to use CREATE_ENTITY you could use a function import, which requires either an entity type or a complex type to be able to return your values from the backend.
I suggest just implementing a simple new entity however.
You can always build upon it in the future, for example when you need to invalidate the token.
To be more specific.
In your SEGW you define a Complex Type myReturnType (it is like a structure) in the Data Model that holds the fields you want to return.
For the Complex Type, no CRUDQ methods are generated.
Then you define a Function Import (getAuth) with Return Type Kind Complex Type and select your created Complex Type (myRetunType) as Return Type. Cardinality probably is 1, but this is up to you.
This is a valid service without entities. And in the backend you only implement the function import

Entity Framework Code First DTO or Model to the UI?

I am creating a brand new application, including the database, and I'm going to use Entity Framework Code First. This will also use WCF for services which also opens it up for multiple UI's for different devices, as well as making the services API usable from other unknown apps.
I have seen this batted around in several posts here on SO but I don't see direct questions or answers pertaining to Code First, although there are a few mentioning POCOs. I am going to ask the question again so here it goes - do I really need DTOs with Entity Framework Code First or can I use the model as a set of common entities for all boundaries? I am really trying to follow the YAGNI train of thought so while I have a clean sheet of paper I figured that I would get this out of the way first.
Thanks,
Paul Speranza
There is no definite answer to this problem and it is also the reason why you didn't find any.
Are you going to build services providing CRUD operations? It generally means that your services will be able to return, insert, update and delete entities as they are = you will always expose whole entity or single exactly defined serializable part of the entity to all clients. But once you do this it probably worth to check WCF Data Services.
Are you going to expose business facade working with entities? The facade will provide real business methods instead of just CRUD operations. These buisness methods will get some data object and decompose it to multiple entities in wrapped business logic. Here it makes sense to use specific DTO for every operation. DTO will transfer only data needed for the operation and return only date allowed to the client.
Very simple example. Suppose that your entities keep information like LastModifiedBy. This is probably information you want to pass back to the client. In the first scenario you have single serializable set so you will pass it back to the client and client pass it modified back to the service. Now you must verify that client didn't change the field because he probably didn't have permissions to do that. You must do it with every single field which client didn't have permission to change. In the second scenario your DTO with updated data will simply not include this property (= specialized DTO for your operation) so client will not be able to send you a new value at all.
It can be somehow related to the way how you want to work with data and where your real logic will be applied. Will it be on the service or on the client? How will you ensure that client will not post invalid data? Do you want to restrict passing invalid data by logic or by specific transferred objects?
I strongly recommend a dedicated view model.
Doing this means:
You can design the UI (and iterate on it) without having to wait to design the data model first.
There is less friction when you want to change the UI.
You can avoid security problems with auto-mapping/model binding "accidentally" updating fields which shouldn't be editable by the user -- just don't put them in the view model.
However, with a WCF Data Service, it's hard to ignore the advantage of being able to write the service in essentially one line when you expose entities directly. So that might make the most sense for the WCF/server side.
But when it comes to UI, you're "gonna need it."
do I really need DTOs with Entity Framework Code First or can I use the model as a set of common entities for all boundaries?
Yes, the same set of POCOs / entities can be used for all boundaries.
But a set of mappers / converters / configurators will be needed to adapt entities to some generic structures of each layer.
For example, when entities are configured with DataContract and DataMember attributes, WCF is able to transfer domain objects' state without creating any special classes.
Similarly, when entities are mapped using Entity Framework fluent mapping api, EF is able to persist domain objects' state in database without creating any special classes.
The same way, entities can be configured to be used in any layer by means of the layer infrastructure without creating any special classes.

ASP.NET, MVC 3, EF 4.1: Filtering data based on ASP.NET Authentication login

If you have a decent layered ASP.NET MVC 3 web application with a data service class pumping out view models pulled from a repository, sending JSON to an Ajax client,
[taking a breath]
what's a good way to add data filtering based on ASP.NET logins and roles without really messing up our data service class with these concerns?
We have a repository that kicks out Entity Framework 4.1 POCOs which accepts Lambda Expressions for where clauses (or specification objects.)
The data service class creates query objects (like IQueryable) then returns them with .ToList() in the return statement.
I'm thinking maybe a specification that handles security roles passed to the data service class, or somehow essentially injecting a Lambda Expression in just the right place in the data service class?
I am sure there is a fairly standardized pattern to implement something like this. Links to examples or books on the subject would be most appreciated.
If you've got a single-tiered application (as in, your web layer and service/data layer all run in the same process) then it's common to use a custom principal to achieve what you want.
You can use a custom principal to store extra data about a user (have a watch of this: http://www.asp.net/security/videos/use-custom-principal-objects), but the trick is to set this custom principal into the current thread's principal also, by doing Thread.CurrentPrincipal = myPrincipal
This effectively means that you can get access to your user/role information from deep into your service layer without creating extra parameters on your methods (which is bad design). You can do this by querying Thread.CurrentPrincipal and cast it to your own implementation.
If your service/data layer exists in a different process (perhaps you're using web services) then you can still pass your user information separately from your method calls, by passing custom data headers along with the service request and leave this kind of data out of your method calls.
Edit: to relate back to your querying of data, obviously any queries you write which are influence by some aspect of the currently logged-in user or their role can be picked up by looking at the data in your custom principal, but without passing special data through your method calls.
Hopefully this at least points you in the right direction.
It is not clear from your question if you are using DI, as you mentioned you have your layers split up properly I am presuming so, then again this should be possible without DI I think...
Create an interface called IUserSession or something similar, Implement that inside your asp.net mvc application, the interface can contain something like GetUser(); from this info I am sure you can filter data inside your middle tier, otherwise you can simply use this IUserSession inside your web application and do the filtering inside that tier...
See: https://gist.github.com/1042173

Data Services with POCO that are dynamicly Created

Try to understand what the options might be with use of WCF Data Services, Basicly i'm trying to abstract a 3rd party http API by making a RestFull services from the 3rd Party set of api calls. On top of this im intrested in the Odata representation and Api support that Data Services.
Example 3rd Party Call,
1)GetAll Vehicles
I want to represent it in a restfull call http://localhost/Vehicles
2)GetVehicleLocation(vehicles)
I want to represent it in a restfull call http://localhost/Vehicles(1)/Location
The challenge im looking at how can i invoke the List {to make it simple} from the web service call. This part is striaght forward where i need some guidance is when were doing the Call 2), since the Location infomation is based off a webservice call passing the Vehcle, Linq to Object is assuming the POCO are filled if im understanding correctly..
This article
Data Services Streaming seems to be on the path...
I'm presently investigating a similar scenario. Since the primary use case for WCF Data Services is exposing your database tables through Entity framework, finding good information on doing anything else is a bit thin on the ground.
What you are trying to do is fairly straightforward in fact, and can be simplified by using the WCF Data Services Toolkit; you want to wrap odata around what
You will need to expose two entity types at the root level, Vehicle and Location
You need a DataService<MyDataContext> as the entry point of the service, this will need to define two IQueryable properties for Vehicles and Locations. You may not really need to access Locations at the root level, but its the only way to make this work with the underlying reflection provider. Without having Location at the root level the service will not expose the metadata for the Location entity.
Your Vehicle entity will need a Location property with a [ForeignProperty] attribute
You must implement a repository for Vehicles having methods named; GetOne(string id), GetAll() and GetLocationByVehicle(string id) method, the id will be the VehicleId that you need to make your api call.
making a Get request on /Vehicles will invoke the GetAll() method on the repository, /Vehicles(1) will invoke the GetOne() method and /Vehicles(1)/Location will invoke the GetLocationByVehicle() method passing in the Id '1'.