Web API alternative for RetrieveSharedPrincipalsAndAccessRequest - dynamics-crm

I am looking for a way to retrieve sharing permissions on specific entities.
Is there a way to do this via the web api?
I am aware of RetrieveSharedPrincipalsAndAccessRequest but since the rest of my tool relies only on the web api i would like to avoid using Organization Service completely.

This request is available in version 9.0 (Dynamics 365 july update)
I believe that your are using 8.x version. In such case this is not that simple but also doable. Simply create a custom Action:
https://msdn.microsoft.com/en-us/library/dn481600.aspx
Actions can be used from workflows, plugins and, what is most useful in this scenario, directly called from WebAPI:
https://msdn.microsoft.com/en-us/library/mt607600.aspx
So for example your call would look like that:
POST [Organization URI]/api/data/v8.2/new_RetrievePrincipalAccessAction HTTP/1.1
Accept: application/json
Content-Type: application/json; charset=utf-8
OData-MaxVersion: 4.0
OData-Version: 4.0
{
"ObjectId": 3,
"ObjectType": "account"
}
Now, you need to create a plugin and register it in Post-Operation of your action (actions generate a custom message that you can use to register plugins). For example:
https://community.dynamics.com/crm/b/magnetismsolutionscrmblog/archive/2017/09/18/how-to-trigger-plugins-on-custom-messages-using-actions-in-dynamics-365
In your plugin, you can of course call the RetrieveSharedPrincipalsAndAccessRequest using standard IOrganizationService and simply put the result in OutputParameters of an action. Most useful would be JSON string:
public void Execute(IServiceProvider serviceProvider)
{
var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
//do the logic retrieve what you want
context.OutputParameters["result"] = someResultAsJsonString;
}
Your JS webAPI call will return
{
result: someResultAsJsonString
}
And you can do whatever you want with this in your JS code :)

Related

Swagger does not show real error message

We are on .NET WebAPI framework and we are using swagger on top of web api for annotations and out of the box UI experience. So far, it just has been working great. However, when I return an error from WebAPI(Http 400) as following code:
return BadRequest("Some error");
However, when I do that, it seems like Swagger is not able to parse the error properly. It basically, show response 0. Which is wrong for sure because when I go to Chrome DevTools, I see that my request had a response of HTTP 400 as I expected.
How can I configure Swagger so that it is able to show the errors correctly? Or should I be throwing my errors a little bit differently to be able to see it in swagger?
You can annotate your actions like this
[ProducesResponseType(typeof(ResponseObjectTypeHere), 200)]
[ProducesResponseType(typeof(ErrorResponseObjectTypeHere), 400)]
You can also add something like this in the xml documentation if you enable swagger to read and use xml documentation
/// <response code="200">Description</response>
/// <response code="400">Description of error</response>
I used those in the .net core web api project with swagger, should be the same for regular .net web api project as well.
You can simply send the exception details to the client by enabling one of ABP's configurations (SendAllExceptionsToClients) in ***.Web.Core Module, like this:
public override void PreInitialize()
{
if (_env.EnvironmentName.ToLower() == "development")
Configuration.Modules.AbpWebCommon().SendAllExceptionsToClients = true;
}
Then you get the exception details on the client. Recommended only during development.

how to upload a file to asp.net core backend with http

Now I use Asp.net core as the server framework. I want to know how to upload a file to an Asp.net core server? I use web api but not the web application. So form submit is no use. The code below doesn't work.
[HttpPost("uploadImage/{accountGuid}")]
public async Task<string> UploadTargetImage(ICollection<IFormFile> files,Guid accountGuid)
{
if (files == null) throw new Exception("File is null");
if (files.Count == 0) throw new Exception("File is empty");
}
I use fiddler to test the API. Like below:
see the fiddler post image
The result of api is File is empty.So the server didn't get the post file.
What should I do? It puzzles me for a long time.
I hava just fix it! The input name in POST must be the same as method param in ASP.NET.

Without the helpers from WebAPI, this can't be the best way to return status codes from MVC6, can it?

While I'm aware that MVC6 isn't released, it looks like it's missing many features of WebAPI and even MVC5. Can I assume that this isn't the way that it'll look on release?
[HttpPost("")]
public async Task<ActionResult> Post(Visit newVisit)
{
var username = User.Identity.GetUserName();
newVisit.UserName = username;
if (await _repository.AddVisitAsync(newVisit))
{
Response.StatusCode = (int) HttpStatusCode.Created;
return Json(newVisit);
}
return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest);
}
Notice the casts in the Reponse.StatusCode and the HttpStatusCodeResult (I do miss just returning Ok(...), Created(...), etc.
Some features from MVC 5 and Web API 2 have not yet been brought over to MVC 6 (which includes Web API). Logging issues at https://github.com/aspnet/Mvc/issues is the right place to request any missing features. Please check for existing issues because many issues are already tracked.
Please note that several APIs got renamed when MVC and Web API got merged because we didn't want to have duplicate APIs, so even though an exact API match might not be there, it could just have a new name.

Use gapi.client javascript to execute my custom Google API

I have a service that is successfully deployed to Google Endpoints and it is accessible through browser.
Now I am trying to load Google API javascript client library to call my services using javascript.
As far as I know, I should do this
gapi.client.load([MY_APP_NAME], 'v1', function() {
var request = gapi.client.[API_NAME].[SERVICE_NAME].[METHOD]();
request.execute(function(jsonResp, rawResp) {...});
);
But I always get an exception at run time complaining about gapi.client.[MY_API_NAME] is undefined. I do the same thing with any Google API (such as Plus) and it works fine. For example, If I load 'plus' API, I will have access to gapi.client.plus... and I can call methods.
Am I missing something? All samples and documents are about Google Service APIs and I could not find a sample for custom APIs (the one that developers write).
I even tried gapi.client.request with different paths (absolute path and relative path) but I get 404 - Not Found error in "status".
var request = gapi.client.request({'path':
'https://[APP_NAME].appspot.com/_ah/api/[SERVICE_NAME]/v1/[METHOD]'
, 'method': 'GET'});
request.execute(function(jsonResp, rawResp) {...});
var request = gapi.client.request({
'path':'/[SERVICE_NAME]/v1/[METHOD]',
'method': 'GET'});
request.execute(function(jsonResp, rawResp) {...});
The problem was a missing parameter in calling gapi.client.load().
I looked at the definition of gapi.client.load at this link https://developers.google.com/api-client-library/javascript/reference/referencedocs#gapiclientload
gapi.client.load(name, version, callback)
which then later I found out is not totally correct and an optional parameter is missing (app_api_root_url).
gapi.client.load(name, version, callback, app_api_root_url)
If the app_api_root_url is missing, the client is loaded for Google Service APIs only (app_api_root_url such as https://myapp.appspot.com/_ah/api)
You can find more details on how to use gapi.client.load() properly at this link https://developers.google.com/appengine/docs/java/endpoints/consume_js
As you can see in the following piece of code, I didn't have ROOT parameter when I was calling gapi.client.load and that is why Google by default was looking at its own service API and obviously could not find my APIs.
var ROOT = 'https://your_app_id.appspot.com/_ah/api';
gapi.client.load('your_api_name', 'v1', function() {
var request = gapi.client.your_api_name.your_method_name();
request.execute(function(jsonResp, rawResp) {
//do the rest of what you need to do
});
}, ROOT);
NOTE: your_app_id is used in ROOT parameter only to load the client script. After loading is done, you will have an object that is named after your API and not your app. That object is like your Java (service) class and you can use to invoke methods directly.

Windows Phone 7 DataServicesClient Request Headers Accept gzip

I have a Windows Phone 7 application that is utilizing the DataServicesClient to access a WCF DataService (ODATA) and I want to ask the service to compress the response.
I know if the Request Headers includes "Accept-Encoding" header with the value of "gzip" the WCF DS will compress the response.
Is there a way to add this header to the Request when using the DataServicesClient on WP7? The Request Headers collection appears to be readonly. What I would like to be able to do is the following (but the Headers property does not have an Add method in this context.)
void entities_SendingRequest(object sender, SendingRequestEventArgs e) { e.Headers.Add("Accept-Encoding", "gzip"); }
Michael
You should be able to modify header collection with following code
private void OnSendingRequest(object sender, System.Data.Services.Client.SendingRequestEventArgs e)
{
e.RequestHeaders["Accept-Encoding"] = "gzip";
}
This looks a lot like your other active question ;)
As mentioned on that question, it looks like the ODATA client has no way for you to modify the headers of a request before it is sent, though you could make a feature request.

Resources