Azure API Management issue with OData - odata

We have an OData v4 API that we are putting behind an Azure API Management (AAM) service, but have run into a problem configuring the routes/oerations. In a nutshell, the issue is that AAM will reject a query for a route/operation unless it is explicitly configured (you get a 404 error), but with OData there can be a route for every attribute (property) of every operation (endpoint). The problem quickly becomes unmanageable.
OData allows you to query an individual attribute/property (eg GET ~/api/Person(1234)/FirstName. If we put this behind AAM, we need to define it as an operation. That's OK as long as there are only a few of these, but it potentially means you quickly have to define hundreds/thousands of operations (unless I've missed something). We have an API with about 35 top level operations. Each resource has 20 attributes on average. That's 700 operations we would need to define. Apart from the work involved, that would be a shocking experience for users of the AAM developer portal.
I'm hoping someone can tell me an easy way to get around this problem. I know I can script the creation of these. You an also get around this problem to some degree if you use an OData $select query parameter (which is what I've suggested in the meantime). I can't get over the feeling I've missed something here. Is there a way of defining some sort of wildcard portion to the operation (eg /Person/*)? I can't find anything like that in the AAM documentation.

Try using URL templates instead of writing them explicitly, i.e. define operations for /{entity}/{property} this way it'll match every entity and every property of every entity. And you could use wildcards as well if you want to capture multiple segments at the end of URL.

Related

Microsoft Graph educationClass expand with select

I'm trying to grab only properties "id" and "userPrincipalName" from the teacher when getting educationClasses with $expand=teacher as parameter. But whatever I do, I keep getting the full teacher/user object.
https://graph.microsoft.com/v1.0/education/classes?$expand=teachers($select=id,userPrincipalName)
But it gives the same result as this one:
https://graph.microsoft.com/v1.0/education/classes?$expand=teachers
What am I doing wrong?
Or is this one of the endpoints where the expand+select feature is not fully supported? I don't want the full teacher object because it contains assignedLicenses, assignedPlans, provisionedPlans and a whole lot of stuff I will never need in this request.
And...it's production, so I'd like to avoid using the BETA endpoint if possible.
Yep, looks like the underlying AAD storage doesn't support expand plus select.
You can see what is happening under the covers by appending the &$whatif to your query.
Not a lot we can do about this, as the AAD team aren't investing in adding richness here right now.

XSLT transform/mapping work - what questions will you ask?

I have been given an assignment. It pertains to integration/transformation using xml/xslt and is deliberately vague. I have been given a sample integration (shown below) and I have been tasked with listing several questions I would ask before delivering this design,
The hypothetical integration
Data Source --> Mapping ---> output
The question is so vague I couldn't think much. I am not looking for anyone to plagiarise from, but I am hoping someone could post some sample questions to help me get started.
Pertinent Information
Note: Stack Overflow is not a place for you to cheat on an interview process. I am providing this information for other users who are looking to familiarize themselves with integrations. If you don't already know what questions to ask here, and are applying for an SOA job, you will likely be fired within a month. Dishonesty can cost a business a lot of money, and if you cheat your way into a job don't be surprised when you get blackballed or worse - perpetuate a harmful stereotype.
There are a variety of questions you would need to ask before implementing this type of integration. Here are a few things that come to mind.
1. What type of integration is this?
There are a variety of different integration paradigms. I would need to know if it is
An app/request driven orchestration
A scheduled orchestration
A file transfer
A pub/sub subscription
2. Is it invoked or triggered
An invoked integration is one that begins when it is specifically called. If I had a REST service that returned a list of countries, and your call that service every time a button was clicked that would be an invocation based integration.
Integrations can also be trigger based. Let's say you had a table that stored customers. You want to send an email whenever a new customer is added to that table. If you set your initial data source (adapter) as a trigger source on a row insert you could essentially have the integration run without explicitly being triggered.
3. What is the data source?
I would need to know if the data source is REST, SOAP, a database (DB2, MySQL, Oracle DB, etc), a customer adapter, etc. IS the data source adapter the entry point here or is the initial app adapter not shown?
4. What is the schema definition of the request / response body, and how is it specified?
You have a data source (which appears to be your initial app adapter), then you have a transformation, and a response. You can't do any transformation (or build an integration) if you don't know what the input / output will be (with some exceptions). This is really a multi level question.
How do I specify the request and response? Do I need to draft a JSON Schema or XSD document? Some platforms allow you to specify XML or JSON and they will do it's best to generate a schema for you.
What is the request and response content type? You can specify the request / response in whatever format is acceptable, but that doesn't necessarily mean that is the request / response type. For example some platforms let you specify your request body with an XSD but the content type is actually JSON. Is it XML, JSON, Plain Text, other?
5. What about other parameters
Basically, what does the endpoint look like? Are there query parameters, template parameters, custom header parameters, etc?
6. How is this integration secured?
Is this integration security using OAuth? If so what type of tokens are used (JWT, etc)? Does the integration use basic authentication?
Based off the answers to the previous questions you may then have questions about the mapping. For example, if I was provided a schema definition for the output that had an attribute called "zip" I might ask how they wish to format that, etc. I wouldn't ask anything about what technology is used for the mapping. Firstly, because it'as almost always XPath/XSLT, secondly that isn't something you need to know, it's something you would figure out on your own.

Web Load Test with MVC route parameters creates many instance URL's

I have a web test for the following request:
{{WebServer1}}/Listing/Details/{{Active Listing IDs.AWE2_RandomActiveAuctionIds#csv.ListingID}}
And I receive the error message:
The maximum number of unique Web test request URLs to report on has been exceeded; performance data for other requests will not be available
because there are thousands of unique URL's (because I'm testing for different values in the URL). Does anyone know how to fix this?
There are a few features within Visual Studio (2010 and above) that will help with this problem. I am speaking for 2010 specifically, and assuming that the same or similar options are available in later versions as well.
1. Maximum Request URLs Reported:
This is a General Option available in the Run Setting Properties of the load test. The default value set here is 1,000. This default value is usually sufficient... but not always high enough. Depending on the load test size, it may be necessary to increase this. Based on personal experience, if you are thinking about adjusting this value, go through your tests first and get an idea of how many requests you are expecting to see reported. For me, a rough guideline that is helpful:
*number_of_request_in_webtest * number_of_users_in_load_test = total_estimated_requests*
If your load test has multiple web tests in it, adjust the above accordingly by figuring out the number of requests in each indvidual test, sum that value up, and multiply by the number of users.
This option is more appropriate for large load tests that are referencing several web tests and/or have a very high user count. One reference for a problem|resolution use-case of this option is here:
https://social.msdn.microsoft.com/Forums/en-US/ffc16064-c6fc-4ef7-93b0-4decbd72167e/maximum-number-of-unique-web-test-requests-exceeded?forum=vstswebtest
In the specific case mentioned in the originally posted question, this would not resolve the problem entirely. In fact, it could create a new one, where you end up running out of virtual memory. Visual Studio will continue to create new request metrics and counters for every single request that has a unique AWE2_RandomActiveAuctionIds.
2. Reporting Name:
Another option, which #AdrianHHH already touched on, is the "Reporting Names" Option. This option is found in the request properties, inside the web test. It defaults to nothing, which in turn, results in Visual Studio trying to create the name that it will use from the request itself. This behavior creates the issue you are experiencing.
This option is the one that will directly resolve the issue of a new request being reported for every unique request report.
If you have a good idea of the expected number of requests to be seen in the load test (and I think it is a good idea to know this information, for debugging purposes, when running into this exception) a debugging step would be to set the "Maximum Request URLs Reported" DOWN to that value. This would force the exception you are seeing to pop up more quickly. If you see it after adjusting this value, then there is likely a request that is having a new reported value generated each time a virtual user executes the test.
Speaking from experience, this debugging step can save you some time and hair when dealing with requests that contain sessionId, GUID, and other similar types of information in them. Unless you are explicitly defining a Reporting Name for every single request... it can be easy to miss a request that has dynamic data in it.
3. Record Results:
Depending on the request, and its importance to your test, you can opt to remove it from your test results by setting this value to false. It is accessed under the request properties, within the web test itself. I personally do not use this option, but it may also be used to directly resolve the issue you are experiencing, given that it would just remove the request from the report all together.
A holy-grail-of-sorts document can be found on Codeplex that covers the Reporting Name option in a small amount of detail. At the time of writing this answer, the following link can be used to get to it:
http://vsptqrg.codeplex.com/releases/view/42484
I hope this information helps.

Does Delicious use GET requests for creation instead of POST, and why shouldn't I do the same?

I'm looking at the Delicious API and see the following is the operation to create a new bookmark:
https://api.del.icio.us/v1/posts/add?&url={URL}&description={description}
It looks like they're using a GET request to create server-side database entries, which I've read elsewhere shouldn't be done with GET requests, only with POST requests.
I'm writing my own API right now and I think that it's fabulous to let users interact with the API directly from the URL. But you can't do this unless you allow CRUD operations over GET.
So, is Delicious really doing CRUD operations over GET? Is there an important reason I shouldn't do the same thing in my API, or is POST just mandated for CRUD to prevent accidental invocation?
Accidental invocation is part of it; that's what the HTTP spec means when it talks about "idempotent" methods. But you could argue that what Delicious is doing is actually idempotent as long as the URL only gets added once no matter how many times you GET. But more importantly is that GET is safe:
The important distinction here is that the user
did not request the side-effects, so therefore
cannot be held accountable for them.
From an interface design standpoint, you want user-agents to make POST and PUT and DELETE more difficult than GET, or at least distinctly different, so that users can rely on that difference to hint when their actions might cause a change in the resource state, because they are responsible for those changes. Using GET to make changes, even if idempotent, blurs that line of accountability, especially when prefetchers are widely deployed.
That depends if you follow the REST principles GET for changing things is forbidden. Therefore most people say with REST use POST for changes.
However there is a difference between GET and POST. According to the RFC GET requests have always a followup RESPONSE. And if you use POST you need to follow the Redirect-After-Post pattern.
Another limitation is that URLs may have a limited size. So GET will only work as long as your input data is short enough. So the delicious API has there a bug. You will not be able to add every possible url via a GET parameter.

How should a REST URL schema look like for a tree hierarchy?

Let's assume that I have stores, shelves in a store, and products on a shelf. So in order to get a list of products on a shelf in a store, I'd use the following request:
GET http://server/stores/123/shelves/456/products
From here, how would I get an individual product? Should I use:
GET http://server/products/789
Or:
GET http://server/stores/123/shelves/456/products/789
The first method is more concise, since once you get a list of products, you don't really care which store it belongs to if you just want to view the details for a particular product. However, the second method is more logical, since you're viewing the products for a specific shelf in a specific store.
Likewise, what about a PUT/DELETE operation?
DELETE http://server/stores/123/shelves/456/products/789
Or:
DELETE http://server/products/789
What would be the correct way of designing a schema for a tree hierarchy like this?
P.S. If I'm misunderstanding something about the REST architecture, please provide examples on how I can make this better. There's way too many people who love to say "REST is not CRUD" and "REST is not RPC", then provide absolutely no clarifications or examples of good RESTful design.
I've noted 2 approaches to RESTful URI design: hierarchical & filtered
I feel hierarchical is overly verbose, has the potential for redundant endpoints (not DRY) and disguises in what resource's state you're really interested (after all, REST = representational state transfer).
I favor Simple URIs
Simple is elegant. I'd choose a URI structure like
GET http://server/products/789
because I am interested in the state of the product resource.
If I wanted all products that belonged to a specific shelf at a specific store, then I would do
GET http://server/products?store=123&shelf=456
If I wanted to create a product at a specific store on a specific shelf then I'd post
{
product: {
store: 123,
shelf: 456,
name: "test product"
}
}
via
POST http://server/products
Ultimately, it's tomayto, tomahto
REST doesn't require one over the other. However, in my own experience, it is more efficient to consume a RESTful API that maps single entities to single endpoints (eg: RestKit object mappings on iOS) instead of having an entity map to many different endpoints based on what parameters are passed.
About REST
As far as REST, it is not a protocol and has no RFC. It is tightly related to the HTTP/1.1 RFC as a way to implement its CRUD actions, but many software engineers will posit that REST does not depend on HTTP. I disagree and consider such as conjecture, because the original dissertation by UCI's Roy Fielding (http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm) explains the deep rooted connection of REST and HTTP/1.1. You may also enjoy Roy's opinion on the topic: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven.
The principles defined by REST can be applied to other protocols, but REST was built for the internet and HTTP is the protocol for the world wide web.
REST vs RPC
RPC is all about making calls to remote functions and is verb-centric.
REST is all about using the CRUD convention to act on data depending on how the CRUD operation applies to a given data type and is noun-centric.
You can accomplish the same things with REST or RPC, but REST follows DRY principles because for every URI you can perform 4 actions whereas RPC requires an endpoint for each action.
PS
Much of this is my opinion and based on my experiences, but I hope it sheds some light on how you could most efficiently design a RESTful URI schema. As always, your specific goals and needs will affect your choices, but simplicity is always a good target for which to aim.
Creating a product should just be a POST to
http://server/product
Updating a product should just be a PUT to
http://server/product/$id
Getting a product should just be a GET to
http://server/product/$id
Deleting a product should just be a DELETE to
http://server/product/$id
You should use the http methods that are there for you to get more functionality out of a simpler uri structure. If creating a product requires a passing in a store and shelf as a requirement, then those should get passed in the body of your POST (or PUT if you're changing shelves).
When someone does a GET to http://server/product/$id, they will get back some kind of xml/json response, right? What does that look like? The incoming data for a create or update should be POSTed or PUT the same way in the body of the request. That is how you pass in the store and shelf, not via the uri. The uri should be as simple as possible and just point to the resource (product), using the http verbs to differentiate functionality.
If you want to be able to get the contents of shelf 23, you do a GET to
http://server/shelf/23
When you do, you get back a json / xml / custom media type document that has the shelf data and a collection of product elements with links back to their product uri.
If you want to be able to move product 23 from one shelf to another, you do a PUT to
http://server/product/23
In the body of the PUT you have the product in the representation of your choice, but with the updated shelf.
It's a weird mode of thinking at first, because you're not dealing with functionality across the entire system, but instead focusing on the resources (product, shelf, store) and using the http verbs to expose them to the universe.
Don't design a REST api based on an URL structure. Here is how I think you should go about designing a REST api.
Trying to define a REST interface without discussing what links will be contained in what resources is like discussing an RPC interface and ignoring parameters and return values.
Since products may be in several stores or several shelves (categories?), I'd have each product have a unique number regardless of its position in the hierarchy. Then use the flat product number. That makes the API more stable when some products are for instance moved in your store.
In short, don't add unneeded redundancy to your API. To get a shelve list a store ID is enough, for a product list a shelve ID is enough... etc.
it seems like you are trying to build many different use cases, but everything is getting built into one super service. It would be better to break it out.
http://server/product_info/123123 or http://server/product_info?product=123123
http://server/product_inventory?store=123&shelf=345
then you can also support:
http://server/product_inventory?store=123
then PUT and DELETE makes sense for changing inventory or adding a new product.

Resources