Easier way to retrieve (all) extended properties for an event? - microsoft-graph-api

As a followup to How to retrieve extended properties for calendar event (by name)? and How to retrieve extended properties of type datetime? :
I actually have to retrieve 4 custom property values (string, datetime, 2 integers).
The URL then becomes (line wraps added by me):
https://graph.microsoft.com/v1.0/users/{{UserID}}/calendar/events/{{TTSyncedEventID}}?$expand=singleValueExtendedProperties(
$filter=id eq 'Integer {00020329-0000-0000-C000-000000000046} Name TTID'
or id eq 'String {00020329-0000-0000-C000-000000000046} Name TTSyncID'
or id eq 'Integer {00020329-0000-0000-C000-000000000046} Name TTSyncVer'
or id eq 'SystemTime {00020329-0000-0000-C000-000000000046} Name TTSyncTime')
That's quite a URL! (note: {{ }} are Postman variables)
Is there an easier way to retrieve (all) extended properties for an event?
The documentation for Get singleValueLegacyExtendedProperty states:
Use a $filter and eq operator on the id property to specify the extended property. This is currently the only way to get the singleValueLegacyExtendedProperty object that represents an extended property.
... which suggests 'no', but maybe there is something smart I can do with the $filter?

Unfortunately, there is no other way to get all extended properties then by specifying their id and eq operator.
$filter parameter doesn't support in operator for singleValueLegacyExtendedProperty, so you can't write something like this
/v1.0/users/{{UserID}}/calendar/events/{{TTSyncedEventID}}?$expand=singleValueExtendedProperties(
$filter=id in ('Integer {00020329-0000-0000-C000-000000000046} Name TTID','String {00020329-0000-0000-C000-000000000046} Name TTSyncID','Integer {00020329-0000-0000-C000-000000000046} Name TTSyncVer','SystemTime {00020329-0000-0000-C000-000000000046} Name TTSyncTime'))

Related

Difference between API ID and API name in Open API?

When opening an API specification in Microsoft Azure API management we are giving some name and the swagger specification file also has some name as title. The name which we have given coming as API id and the title available in the Swagger.json is coming as API display name. So what is the difference between API id and API name in Azure API management?
It's common to all Azure resources to have name and id. Resource id is full "resource path" that goes like "/subscriptions/.../resourceGroups/.../providers/...". Last segment of that path is resource name.
Name is fixed field of the Contact Object in OpenAPI.
Name reflects the identifying name of the contact person/organization.
There's no id field in Contact object or any other openapi description fields, but openapi file may have user made id parameter.
Please, see this example:
parameters:
- name: id
in: path
description: ID of pet to use
required: true
schema:
type: array
style: simple
items:
type: string
Take a look at operationId. operationId is an optional unique string used to identify an operation. If provided, these IDs must be unique among all operations described in your API.

How to verify if a field is an empty string with GORM?

I have a GORM query and I need to make it avoid a field which may be a empty string for legacy system questions.
Currently, my query is:
def things = Thing.withCriteria{
resultTransformer CriteriaSpecification.ALIAS_TO_ENTITY_MAP
createAlias 'factor', 'f'
eq 'active', true
isNotNull 'title' // this field may be an empty string
isNotNull 'content' // this field also may be an empty string
// <-- and here I'd like to include sth like isEmpty 'title'
not {
inList 'f.id', factors
}
projections{
property 'id' , 'id'
property 'f.name' , 'name'
property 'title' , 'title'
property 'content' , 'content'
property 'f.id' , 'factorId'
}
}
I didn't find any solution in the docs, but I have a feeling that this solution should be with pure SQL. Is it possible? Any suggestion?
Have you tried adding this statement to the criteria?
ne title, ""
Grails criteria relies on hibernate Restrictions, so everything supported by this can also be used in grails criteria.
Otherwise you could also use sql restrictions (see Using SQL Restrictions section):
sqlRestriction "char_length(title) > 0"
Keep in mind that title here refers to the real column name in the database. If you want to have a more reliable code, you can include a static mapping for the field (column name) in the model :
static mapping = {
title column: 'title'
}
In this way you should avoid errors from db specific naming behaviour (if any).

Error while querying Breeze with predicate on DateTimeOffset column

I am trying to query my entity with a predicate on a DateTimeOffset column, but getting a 500 error response from the Breeze.WebApi. The error message is
Unable to perform operation: leon types:System.Nullable`1[System.DateTimeOffset], System.DateTime
The uri I see produced is something like
http://localhost:49800/api/Breeze Orders?$filter=LocalDateTime%20le%20datetime'2013-03-03T00%3A00%3A00.000Z'
What is working:
I can query on other DateTime, text columns
I can save new data into my 'LocalDateTime' field
The full error response from the query is:
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Unable to perform operation: leon types:System.Nullable`1[System.DateTimeOffset], System.DateTime
</ExceptionMessage>
<ExceptionType>System.Exception</ExceptionType>
<StackTrace>
at Breeze.WebApi.ParseTreeVisitor.CoerceTypes(String operatorName, Expression& leftExpr, Expression& rightExpr) at Breeze.WebApi.ParseTreeVisitor.VisitBinary(ParseTreeNode node, String operatorName, Expression leftExpr, Expression rightExpr) at Breeze.WebApi.ParseTreeVisitor.VisitNode(ParseTreeNode node) at Breeze.WebApi.ParseTreeVisitor.Parse(Type rootType, ParseTreeNode node) at Breeze.WebApi.ExpressionTreeBuilder.Parse(Type rootType, String source) at Breeze.WebApi.ODataActionFilter.BuildFilterFunc(String filterQueryString, Type elementType) at Breeze.WebApi.ODataActionFilter.OnActionExecuted(HttpActionExecutedContext actionExecutedContext) at System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecuted(HttpActionContext actionContext, HttpResponseMessage response, Exception exception) at System.Web.Http.Filters.ActionFilterAttribute.<>c__DisplayClass2.<System.Web.Http.Filters.IActionFilter.ExecuteActionFilterAsync>b__0(HttpResponseMessage response) at System.Threading.Tasks.TaskHelpersExtensions.<>c__DisplayClass41`2.<Then>b__40(Task`1 t) at System.Threading.Tasks.TaskHelpersExtensions.ThenImpl[TTask,TOuterResult](TTask task, Func`2 continuation, CancellationToken cancellationToken, Boolean runSynchronously)
</StackTrace>
</Error>
.
EDIT
Getting there, but not quite. After installing Breeze 1.2.8 the client is now generating correctly typed uri e.g.
http://localhost:49800/api/Breeze/Orders?$filter=LocalDateTime%20ge%20datetimeoffset'2013-01-01T11%3A00%3A00.000Z'
In my case using setEntityTypeForResourceName to fix the entity type isnt needed. The above uri still gives me the error:
Unable to perform operation: leon types:System.Nullable`1[System.DateTimeOffset], System.DateTimeOffset
Changing my server side model from
public Nullable<System.DateTimeOffset> LocalDateTime { get; set; }
to
public System.DateTimeOffset LocalDateTime { get; set; }
allows my uri to work.
So can we please have a fix for nullable DateTimeOffset.
This is fixed in v 1.2.7. Please post back if you still see the error.
--- Further information ---
There have been several posts since 1.2.7 indicating that this error was still occuring. It turns out that the issue is NOT that breeze doesn't understand 'dataTimeOffsets'. It is that breeze is very forgiving of incorrect EntityType/Resource name mappings in queries except in the case of queries involving 'DateTimeOffsets'. This post is a bit long, so if you just need the fix, read the last paragraph.
The "Unable to perform operation: ... " error occurs when executing a query against a dateTimeOffset property when the resource name declared in the query ( the value in the 'from' clause) cannot be mapped to an existing entityType name (defined in metadata).
If breeze can find an entity type that maps to the resource name declared in the query, it uses the metadata for that entityType to validate the query and create an OData filter string. However, if it can't find a matching entity type, which is a perfectly acceptable condition because some 'resourceName's will not map to entities, it tries to infer the datatypes involved in any query clauses by looking at any constant parameters involved in the query and using their datatype. The problem is that a javascript date object can be mapped to either a .NET 'DateTime' or a 'DateTimeOffset' and Breeze can only pick one and in this case picks the 'wrong' one.
This kind of mismapping does not cause problems when data is returned from a query because breeze only uses the entity type of the query to validate and construct an appropriate OData filter string. Data returned from any query is inspected to determine the entityTypes of each item returned so the resourceName/entityType mapping is not needed. ( A single query may return multiple entity types because of the use of 'expand' or 'select' clauses.)
The root cause of the mapping issue involves the map of resource names to entity types that breeze keeps in each MetadataStore. This mapping is available via the MetadataStore.getEntityTypeNameForResourceName and MetadataStore.setEntityTypeForResourceName methods. When using Entity framework metadata, breeze assumes that Entity Framework 'EntitySet' names correspond to 'resourceNames'. This assumption is what is causing the problem. If you query a 'resourceName' that is different from one of your EntitySet names, Breeze does not know the corresponding 'entity Type' and falls back on inferring the datatypes used in the query, instead of using the 'entity Type' metadata.
There are two fairly simple fixes, either of which work.
1) Use the MetadataStore.setEntityTypeForResourceName method to map your resource names to your entity types. Note that you can have as many resource names as you like mapped to the same entity type.
2) Name your methods ( that correspond to resource names) to the names of the corresponding EntitySet defined in EF and not the name of the type that is returned. A common convention is that EntitySet names ( and hence resource names) are pluralized, whereas EntityType names are usually singular. i.e. 'Customers' is a resource name and 'Customer' is the EntityType

How to address entity that uses composite identity key in OData Url?

I have an entity OrderItem that has OrderId and ProductId integer fields and these two fields form the identity key/primary key for this table.
I would like to use OData/Web API to expose such entities through a service and to be able to select OrderItem instances by they composite ID.
What should be the format of the URL?
Are there any best practices for handling such scenarios?
Composite keys in the URL use syntax like this:
~/OrderItems(OrderId=1234,ProductId=1234)
The "grammar" is defined in the OData ABNF Construction Rules (see the definition for "compoundKey")
An example usage can be found in OASIS' OData Version 4.0. Part 2: URL Conventions Plus Errata 03
Note that the "composite key" (aka "complex key predicate") has been around since OData 1.0.
First, you have to make sure that you explicitly mention that it has a composite key, in configuration file
builder.EntityType<OrderItem>().HasKey(t => new { t.OrderId, t.ProductId});
Then, the action should have the following header
public SingleResult<OrderItem> Get([FromODataUri] string keyOrderId, [FromODataUri] string keyProductId)
Please note the prefix(key) used for both parameters!
This is OData V4. Please also refer to https://odata.github.io/WebApi/13-06-KeyValueBinding/

How to control the serialization of types in RouteValueDictionary?

I have code that builds Urls in ASP.NET MVC3 using a RouteValueDictionary and UrlHelper. The problem that I am running into is that MVC calls ToString() on the types in the dictionary. For a particular type I am using, this is not the value that I want to be in the Uri. I cannot change the ToString implementation.
I understand how to create a ModelBinder to handle the deserialization from the Uri, but not the serialization part. How and what do I register in order to control how a type is converted to the Uri parameter?
Thanks,
Erick
For a particular type I am using, this is not the value that I want to be in the Uri
Then don't use this type. Pass the value that you want directly as string in the dictionary:
rvd["key"] = "the value you want";
instead of:
rvd["key"] = new SomeType { Foo = "foo", Bar = "bar" };
The conversion between your type and its string representation should be handled elsewhere.

Resources