Setting custom properties on an 365 group with GraphClient - microsoft-graph-api

I want to set CustomProperty5 on a 265 group. I have following code:
var extensions = await graphClient.Groups["xxx"].Extensions.Request().GetAsync();
var dictionary = new Dictionary<string, object>();
dictionary.Add("CustomAttribute5", "Works!");
await graphClient
.Groups["xxx"]
.Request()
.UpdateAsync(new Microsoft.Graph.Group()
{
AdditionalData = dictionary
});
However I get following error:
Microsoft.Graph.ServiceException: 'Code: Request_BadRequest Message:
One or more property values specified are invalid.
Any pointers how to set custom properties on a 365 group?

For existing group open extension could be updated like this via msgraph-sdk-dotnet:
//retrieve an existing group custom property
var ext = await graphClient.Groups[groupId].Extensions[extName].Request().GetAsync();
//update
ext.AdditionalData = new Dictionary<string, object>()
{
{
"status", "Closed"
}
};
await graphClient.Groups[groupId].Extensions[extName]
.Request()
.UpdateAsync(ext);
When it comes to complex type extension, it could be updated via group update endpoint. Lets assume the following type extension is registered:
{
"id":"contoso_grpstatus",
"description": "",
"targetTypes": [
"Group"
],
"properties": [
{
"name": "Status",
"type": "String"
}
]
}
Then an existing group instance with the contoso_grpstatus complex type extension defined could be updated like this:
var group = new Group
{
AdditionalData = new Dictionary<string, object>()
{
{
"contoso_grpstatus", new Dictionary<string, object>()
{
{"Status", "Closed"}
}
}
}
};
await graphClient.Groups[groupId]
.Request()
.UpdateAsync(group);

Related

How to display IdentityServer endpoints in SwaggerUI with Swashbucke

I have an ASPNET Core 6 service which uses Duende IdentityServer 6, which includes several endpoints such as /connect/token and /connect/authorize. I need these endpoints to show up in my Swagger UI page, however I cannot find a way to get them to show up.
Here is my AddSwaggerGen
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "API", Version = "v1" });
c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
ClientCredentials = new OpenApiOAuthFlow
{
AuthorizationUrl =
new Uri($"{builder.Configuration.GetSection("BaseUri").Value}connect/authorize",
UriKind.RelativeOrAbsolute),
TokenUrl = new Uri($"{builder.Configuration.GetSection("BaseUri").Value}connect/token",
UriKind.RelativeOrAbsolute),
Scopes = new Dictionary<string, string>
{
{ Constants.Api.ScopeName, "Base level access to API" }
}
}
}
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" },
In = ParameterLocation.Cookie
},
new string[] { }
}
});
});
And I am just using the basic app.AddSwagger() and app.AddSwaggerUI()
As far as my research has shown, CodingMytra is correct. IdentityServer endpoints must be added manually to the Swagger document.

Update SharePoint document library item hyperlink field using using Microsoft Graph in C#

I'm trying to update a SharePoint document library item's hyperlink field using Microsoft Graph in C#.
I'm using Microsoft.Graph 4.10.0 to update the hyperlink in SharePoint. This is the code I have tried which give me an Invalid request error.
var fieldValueSet = new FieldValueSet
{
AdditionalData = new Dictionary<string, object>
{
{"OriginalImageLink", new Dictionary<string, string>{{"https://example.com/img1.jpg", "https://example.com/img1.jpg"}}}
}
};
await GraphClient.Sites["siteId"].Lists["listId"].Items["listItemId"].Fields.Request().UpdateAsync(fieldValueSet);
I can update a text field in SharePoint which works fine:
var fieldValueSet = new FieldValueSet
{
AdditionalData = new Dictionary<string, object>
{
{"Comment", "This is my comment"}
}
};
I can also update the hyperlink using HTTP:
PATCH https://graph.microsoft.com/v1.0/sites/{site-id}/lists/{list-id}/items/{item-id}/fields
Content-Type: application/json
{
"OriginalImageLink": {"Url": "https://example.com/img1.jpg", "Description": "https://example.com/img1.jpg"}
}
Conclusion: I can't update a SharePoint hyperlink field using C#. But I can update a text field in SharePoint and I can update the hyperlink using HTTP.
How do I update the SharePoint hyperlink field using C#?
Update:
This feature is currently not supported. Upvote this feature
Did you try to specify Url and Description fields in fieldValueSet?
var fieldValueSet = new FieldValueSet
{
AdditionalData = new Dictionary<string, object>
{
{ "OriginalImageLink", new Dictionary<string, string>
{
{ "Url" , "https://example.com/img1.jpg" },
{ "Description", "https://example.com/img1.jpg"}
}
}
}
};
await GraphClient.Sites["siteId"].Lists["listId"].Items["listItemId"].Fields
.Request()
.UpdateAsync(fieldValueSet);
Update:
According to this answer the update of sharepoint listitem with hyperlink field is not supported.

Adding an Entitlement Management Access Package Catalog Owner with Graph API

I'm working with Microsoft.Graph.Beta 4.0.1-preview and the beta API endpoint to do bulk provisioning of Entitlement Management Access Package Catalogs. One area that appears to be undocumented is how to assign roles like Catalog owner. I've been able to get the existing Role Assignments:
var assignments = await graphClient.RoleManagement.EntitlementManagement.RoleAssignments
.Request()
.Filter($"roleDefinitionId eq '{roleDefinitionId}' and principalId eq '{principalId}'")
.GetAsync();
I'm getting an InvalidModel error when I try to create new Role Assignment:
var assignment = new UnifiedRoleAssignment
{
RoleDefinitionId = role.Id,
PrincipalId = catalogRole.PrincipalId.ToString(),
AppScopeId = $"/AccessPackageCatalog/{catalogId}"
};
await graphClient.RoleManagement.EntitlementManagement.RoleAssignments
.Request()
.AddAsync(assignment);
The code above is very close to the examples given for assigning a Directory Role, but alas the API is returning an InvalidModel error.
I'm sure that I have the correct RoleDefinitionId and PrincipalId, and I copied the AppScopeId format from an existing Role Assignment:
I'm half convinced that I'm trying to add the new Role Assignment in the wrong place in the API.
I found a work-around for anyone else that needs to do this:
If I serialize a Beta.UnifiedRoleAssignment and send a POST to Graph I also get an InvalidModel error. All of the uninitialized properties are included in the JSON. Not sure if this is how the Beta Graph SDK is behaving, this is just what happens if I serialize a UnifiedRoleAssignment manually:
{
"appScopeId": "/AccessPackageCatalog/603b69ff-283e-4fa3-a7aa-99d51aa4040d",
"condition": null,
"directoryScopeId": null,
"principalId": "d8f2b33d-fca2-43c9-991c-a45ae674532f",
"resourceScope": null,
"roleDefinitionId": "e2182095-804a-4656-ae11-64734e9b7ae5",
"appScope": null,
"directoryScope": null,
"principal": null,
"roleDefinition": null,
"id": null,
"oDataType": "microsoft.graph.unifiedRoleAssignment",
"additionalData": null
}
If I instead serialize a work-around object that only contains the properties I'm setting I am able to create the Role Assignment:
{
"roleDefinitionId": "e2182095-804a-4656-ae11-64734e9b7ae5",
"principalId": "c251d039-15aa-4104-8d5b-f91d95da61d9",
"appScopeId": "/AccessPackageCatalog/603b69ff-283e-4fa3-a7aa-99d51aa4040d"
}
Here's the C#:
public class UnifiedRoleAssignmentWorkaround
{
public string AppScopeId { get; set; }
public string PrincipalId { get; set; }
public string RoleDefinitionId { get; set; }
}
...
var assignment = new UnifiedRoleAssignmentWorkaround()
{
RoleDefinitionId = role.Id,
PrincipalId = catalogRole.PrincipalId.ToString(),
AppScopeId = $"/AccessPackageCatalog/{catalogId}"
};
var message = new HttpRequestMessage(HttpMethod.Post, "https://graph.microsoft.com/beta/roleManagement/entitlementManagement/roleAssignments");
var jsonOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);
var assignmentJson = JsonSerializer.Serialize(assignment, typeof(UnifiedRoleAssignmentWorkaround), jsonOptions);
message.Content = new StringContent(assignmentJson, Encoding.UTF8, "application/json");
await graphClient.HttpProvider.SendAsync(message);

Swashbuckle Swagger Asp.Net Core Pass Api Key as Default Header Value in Request

I have basic Api that accepts a default header value for my-api-key and the corresponding value.
I'm trying to get the Swagger UI to allow me to enter the header one time for Authorization and have the key/value passed along with every request.
So far, I've only been successful with explicitly adding the header as a parameter to every endpoint, but that isn't ideal.
Relevant code snippets:
services.AddApiVersioning(
options =>
{
// reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions"
options.ReportApiVersions = true;
});
services.AddVersionedApiExplorer(
options =>
{
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
// note: the specified format code will format the version as "'v'major[.minor][-status]"
options.GroupNameFormat = "'v'VVV";
// note: this option is only necessary when versioning by url segment. the SubstitutionFormat
// can also be used to control the format of the API version in route templates
options.SubstituteApiVersionInUrl = true;
});
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Api", Version = "v1" });
c.SwaggerDoc("v2", new OpenApiInfo { Title = "Api", Version = "v2" });
// this isn't ideal as I have to fill in the Api Key on ever request
//c.OperationFilter<ApiKeySwaggerFilter>();
c.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.ApiKey,
Name = "my-api-key",
In = ParameterLocation.Header
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{ new OpenApiSecurityScheme()
{
// Type = SecuritySchemeType.ApiKey,
Name = ""
//In = ParameterLocation.Header
//Reference = new OpenApiReference()
//{
// Id = "myToken",
// Type = ReferenceType.SecurityScheme
//},
}, new string[] { }
}
});
});
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Api v1");
c.SwaggerEndpoint("/swagger/v2/swagger.json", "Api v2");
});
Corresponding image of where I'm at:
Corresponding minimal spike: https://github.com/aherrick/SwaggerSample
I feel this is close, but how do I get the Api Header to get passed on every request, without having to force the user to fill in parameter on every method request.
Figured it out with the following section update:
c.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme
{
Description = "Enter your Api Key below:",
Name = "my-api-key",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "ApiKey"
},
},
new List<string>()
}
});

Flutter Firestore add new document with Custom ID

How to add new document with custom id using Dart and Flutter?
PS: I can add new document to collection but its id sets randomly, using this code
postRef.add(data);
which postRef is CollectionReference and data is Map<String, dynamic>
You can use set() function instead of add().
Here's full code:
final CollectionReference postsRef = Firestore.instance.collection('/posts');
var postID = 1;
Post post = new Post(postID, "title", "content");
Map<String, dynamic> postData = post.toJson();
await postsRef.doc(postID).set(postData);
I hope that help anyone.
Update 2021:
Instead of using add, use set on the document.
var collection = FirebaseFirestore.instance.collection('collection');
collection
.doc('doc_id') // <-- Document ID
.set({'age': 20}) // <-- Your data
.then((_) => print('Added'))
.catchError((error) => print('Add failed: $error'));
String uniqueCode = //Your Unique Code
DocumentReference reference = Firestore.instance.document("test/" + uniqueCode );
//Setting Data
Map<String, String> yourData;
reference.setData(yourData);
You can try this code to insert new Document with customID
DocumentReference<Map<String, dynamic>> users = FirebaseFirestore
.instance
.collection('/users')
.doc("MyCustomID");
var myJSONObj = {
"FirstName": "John",
"LastName": "Doe",
};
users
.set(myJSONObj)
.then((value) => print("User with CustomID added"))
.catchError((error) => print("Failed to add user: $error"));

Resources