Modifying the SAS key for Service Endpoint from c# script CRM - c#

I have Service Endpoint for D365 (CRM online) to connect with Azure Service Bus during registration I've specified SAS key from Service Bus Queue and everything works as expected.
Currently, I need to modify the SAS key for some environments but I would prefer to do it from c# script to avoid manual actions. During the investigation, I've found out service endpoint info in the entity "serviceendpoint" and SAS key should be in the "authvalue" field.
I'm trying to perform a regular update for this field but no lack. For some reason, it is impossible to perform a regular update for it.
Could anybody share ideas on how to update the SAS key from the c# script?

I know this comes a little late but I found myself in this exact situation and this is working for me:
// get the CRM endpoints
var query = new QueryExpression("serviceendpoint");
query.ColumnSet.AddColumns("name", "serviceendpointid", "saskeyname");
query.Criteria.AddCondition("name", ConditionOperator.EndsWith, busName);
var queryResult = client.RetrieveMultiple(query);
foreach (var entity in queryResult.Entities)
{
var updateEntity = new Entity(entity.LogicalName, entity.Id);
updateEntity["namespaceaddress"] = nameSpace;
updateEntity["saskeyname"] = sasName;
updateEntity["saskey"] = sasKey;
client.Update(updateEntity);
}
Partly working because I don't get an error and I can see the saskeyname attribute changing on the Plugin Registration Tool, but then the endpoint stops sending data. I then overrode it with the key on that same tool and it worked again, so from what I can see I can update the values but there's something special about that field I just couldn't find anything on the documentation.
Hope this helps someone, and if anyone knows what I'm missing please just let me know

Related

Azure fluent management api bind custom root domain to app service

I've been having trouble with this for a while and now I really need help.
This is the code I am currently using to bind a custom subdomain to Azure and everything is working just fine:
var appService = await azure.AppServices.WebApps.GetByIdAsync(
"subscription-id");
await appService.Update().DefineHostnameBinding()
.WithThirdPartyDomain("mydomain.net")
.WithSubDomain("www")
.WithDnsRecordType(CustomHostNameDnsRecordType.CName)
.Attach()
.ApplyAsync();
So what will be the way to bind just mydomain.net except that CustomHostNameDnsRecordType.CName should be changed with CustomHostNameDnsRecordType.A because Azure does not support CNAME records for root domains?
I cannot skip the WithSubDomain(string) method. Tried passing and null/empty string/space or just . but the response from Azure for null is Object reference not set to an instance and for the others is Bad Request.
P.S. I know that I am using an old SDK which is in maintenance mode but the new ones are still in beta or even alpha and there is still no support for App Services so I have to stick with that.
#DeepDave-MT pointed me to the correct answer in a comment under my question even though it's ridiculous. I am now quite sure I will go with this fluent API because there are too many things that are bothering me, almost no documentation, bad error handling and so on. Anyway, this is how to add a root domain in Azure using the so called fluent management API:
await appService.Update().DefineHostnameBinding()
.WithThirdPartyDomain("mydomain.net")
.WithSubDomain("#")
.WithDnsRecordType(CustomHostNameDnsRecordType.A)
.Attach()
.ApplyAsync();
P.S. I don't know why I don't have the habit to check for issues in GitHub.

How to update the record in an azure function triggered by a webhook?

I have an Azure function triggered post creation of a record in Dynamics 365 CE. The azure function and Dynamics 365 CE are integrated by a Webhook registered via the Plugin Registration.
What is the best way to update some data fields inside the record in RemoteExecutionContext .
Do I connect to Dynamics again or I can update as part of the Dynamics pipeline?
I have tried the .InputParameters["Target"].Id but upon updating with a new HttpClient I am getting a record not found error, whereas the webhook is in Post.
JObject Obj1 = new JObject();
Obj1.Add(STATE, 1);
Obj1.Add(STATUS, 123);
obj1.Add(ERROR_MESSAGE, "Update");
HttpRequestMessage updateApiRequest = new HttpRequestMessage(new HttpMethod("PATCH"), $"{d365Client.BaseAddress}new_customeentity1({targetEntity.Id.ToString()})");
updateApiRequest.Content = new StringContent(obj1.ToString(), Encoding.UTF8, "application/json");
HttpResponseMessage updateResposne = await d365Client.SendAsync(updateApiRequest );
What's the best way to achieve a similar integration?
How can I update the record within the pipeline without getting the Record Not Found error?
I would check two things for solving this particular "record not found" issue:
Try to register the step in "Asynchronous" mode if it's registered as "Synchronous" Read more
Verify the code sample & important points explained in this blog. Basically to avoid sandbox limitations and External Integration purpose only we go for Azure functions/webhooks
So, if you are not doing anything else other than this simple update back to CRM record, then complete the service.Update in post-create plugin itself.

Google Datastore authentication issue - C#

I'm trying to connect to the Google Datastore on my account with service account credentials file (which I've created according to the documentation), but I'm encountering with authentication error while trying to insert an entity:
Grpc.Core.RpcException: Status(StatusCode=Unauthenticated,
Detail="Exception occured in metadata credentials plugin.")
My code is:
var db = DatastoreDb.Create("myprojectid");
Entity entity = new Entity{
Key = db.CreateKeyFactory("mykindname").CreateIncompleteKey()
};
var keys = await db.InsertAsync(new[] { entity });
The GOOGLE_APPLICATION_CREDENTIALS variable refers to the credentials file and when calling GoogleCredential.GetApplicationDefaultAsync() to see if the credentials object is valid it indeed looks good...
I saw some earlier examples which used the GetApplicationDefaultAsync function togehether with some DatastoreService object - but I couldn't find the DatastoreService object (probably it was there in old versions...) in the latest .Net API: Google.Cloud.Datastore.V1
Notice that I don't want to use the other authenticaiton methods:
1) Using the gcloud cli.
2) Running from Google environment (app engine for example).
Any idea how to solve this?
After the great help of Jon Skeet the issue was solved.
The authentication issues can occur if you don't reference all the required Datastore dlls. Make sure that all the dlls are referenced on the project that are running the calls to the Datastore.
I've added the Google Datastore lib via the NuGet to my test project and everything worked!
Notice that in such cases it is recommended to enable gRPC logging. `(For exmaple: GrpcEnvironment.SetLogger(new ConsoleLogger()), there you'll probably see if there were issues loading several dlls...
Authentication can be broken if your system clock is significantly incorrect. Check your system time, and fix it if necessary, then try authenticating against Datastore again.

CRM 2013 Get CRM URL via Custom Workflow

I have a requirement for getting a CRM URL via a custom workflow to use in the next step which is to send an email. The reason for this is to differentiate to users which server this email has come from (UAT/Live).
I have been trying to use HTTPContext route as advised from this site https://social.microsoft.com/Forums/en-US/31ff567d-65ea-4385-a764-68a2121ae8c0/ms-crm-2011-get-path-of-crm-server-url-in-plugin?forum=crmdevelopment but the result I get back is useless as I am I am only receiving an "/" back.
Does anyone know what to do from this point or why this may not be working?
This can't be accomplished, in a supported manner, without creating a connection to the CRM Discovery Service, which requires that you supply credentials. The organization service, available in the workflow does not have a method for discovering the organization's URL.
You have two options:
1) Pass it to the workflow as a parameter using the InputParameter code attribute on your CodeActivity.
2) Create (if you don't already have one) a configuration entity to store the URL and retrieve it in your code.
If you don't really need the URL (i.e., you are not creating a link) then you could just query the Organization entity for the Name attribute. That will give you the Organization's name - which would be the only unique part of the URL. This would allow you to indicate to the user if the Email was coming from UAT or Prod.
I ended up coming up with a solution by using the environment.machinename to pull through the server name. From there i could determine which production server the workflow had been run through and passed a string containing, dev, uat or live to the output to use in my activity emails.
Be aware i had to register the workflow without it being in sandbox mode. Hope this helps somebody in the future.
This was an extremely old question but I came across it while attempting to do something similar.
I found that there is a RetrieveCurrentOrganizationRequest request which was introduced in v9. This will work in sandboxed plugins.
You can use this to retrieve the endpoint urls like so
var currentOrg = base.OrgService.Execute(
new RetrieveCurrentOrganizationRequest()
) as RetrieveCurrentOrganizationResponse;
var url = currentOrg.Detail.Endpoints
.Where(e => e.Key == EndpointType.WebApplication)
.FirstOrDefault()
.Value;
More information here: RetrieveCurrentOrganizationRequest
When I used it, I found that there are 3 available URLs in the Endpoints collection:
Web Application
Organization Data Service
Organization Service
Relevant to CRM 2013 (which the OP was using at the time), there is also the RetrieveOrganizationRequest class which does the same as above; however you have to specify the Organization (and some other information)

WCF CustomToken error " security token with the 'Basic' attachment mode must be signed."

So I have created a custom token, based mostly from the MSDN example (http://msdn.microsoft.com/en-us/library/ms731872.aspx) but I can't seem to get it to work. I always get this error " security token with the 'Basic' attachment mode must be signed." in the logs. I have been over the code base several times and
A) obviously it compiles and runs
B) I can't see where the issue is.
The log message isn't all that helpful. I thought it might be something with the cert but I have beat that to death and created a couple different certs (one using server name set to localhost etc...).
A Google search for this turns up almost nothing.
Anyone got a clue what this is, or just tell me where I can maybe look? Like I said - I have been through this code many times, I see the authorization policy get created and all that good stuff, I can see the certificate is set, I just don't know where else to look, I really don't have any code to post, there are so many classes you have to implement. If someone has an idea of what maybe I can look at I will be happy to post that particular class / code snippet.
Thanks
See here: http://social.msdn.microsoft.com/forums/en-us/wcf/thread/F822CCB9-A8A1-474F-87AF-E5CD9EC34494
... wasn't copying the "id" property of the security token correctly.
This was causing a new ID to get created for the security token on the server, which no longer matched the security signature data, and so the message would be rejected.
In your implementation of your custom WSSecurityTokenSerializer to serialize your security token, you probably aren't copying the Id property of the token. The ID needs to match from the client to the server.
A common mistake (one that I'm sure I've made too) is to just id = Guid.NewGuid().ToString() in the constructor. That is fine for its initial creation on the clinet, but when it deserializes on the server, it needs to use the same ID from the client, not a new guid again.

Categories