How to add a new Enterprise Resource to Resource center in SharePoint 2019 through CSOM - project-server

using (var Context = new ProjectContext(PWA_Url))
{
Load resources and custom fields
Context.Load(Context.EnterpriseResources);
Context.Load(Context.CustomFields);
Context.Load(Context.LookupTables);
Context.ExecuteQuery();
var newResourceId = Guid.NewGuid();
var newResourceInfo = new EnterpriseResourceCreationInformation
{
Id = newResourceId,
IsBudget = false,
IsGeneric = false,
IsInactive = false,
Name = "Test_User",
ResourceType = EnterpriseResourceType.Work
};
Context.EnterpriseResources.Add(newResourceInfo);
Context.EnterpriseResources.Update();
Context.Load(Context.EnterpriseResources);
Context.ExecuteQuery();
}
Getting timeout error on Context.ExecuteQuery();
But after 50 mins the resource is getting created in the resource center
As we need to upload multiple resources its getting error on the first go itself.

Related

AWS Route53 Recovery Controller error when getting or updating the control state using .net

I am trying to get Amazon's Route53 Recovery Controller to update control states from a .net application and I keep getting an error. I see on the documentation that I need to set the region and cluster endpoint, but I can't figure out how to do it.
Here a sample of the code I am using:
AmazonRoute53RecoveryControlConfigConfig configConfig = new AmazonRoute53RecoveryControlConfigConfig();
configConfig.RegionEndpoint = RegionEndpoint.USWest2;
AmazonRoute53RecoveryControlConfigClient configClient = new AmazonRoute53RecoveryControlConfigClient(_awsCredentials, configConfig);
DescribeClusterResponse describeClusterResponse = await configClient.DescribeClusterAsync(new DescribeClusterRequest()
{
ClusterArn = "arn:aws:route53-recovery-control::Account:cluster/data"
});
foreach (ClusterEndpoint clusterEndpoint in describeClusterResponse.Cluster.ClusterEndpoints)
{
AmazonRoute53RecoveryClusterConfig clusterConfig = new AmazonRoute53RecoveryClusterConfig();
clusterConfig.RegionEndpoint = RegionEndpoint.GetBySystemName(clusterEndpoint.Region);
AmazonRoute53RecoveryClusterClient client = new AmazonRoute53RecoveryClusterClient(_awsCredentials, clusterConfig);
GetRoutingControlStateResponse getRoutingControlStateResponseWest = await client.GetRoutingControlStateAsync(new GetRoutingControlStateRequest()
{
RoutingControlArn = "arn:aws:route53-recovery-control::Account:controlpanel/data/routingcontrol/data"
});
GetRoutingControlStateResponse getRoutingControlStateResponseEast = await client.GetRoutingControlStateAsync(new GetRoutingControlStateRequest()
{
RoutingControlArn = "arn:aws:route53-recovery-control::Account:controlpanel/data/routingcontrol/data"
});
UpdateRoutingControlStatesRequest request = new UpdateRoutingControlStatesRequest();
request.UpdateRoutingControlStateEntries = new List<UpdateRoutingControlStateEntry>()
{
new UpdateRoutingControlStateEntry()
{
RoutingControlArn = "arn:aws:route53-recovery-control::Account:controlpanel/data/routingcontrol/data",
RoutingControlState = getRoutingControlStateResponseWest.RoutingControlState == RoutingControlState.On ? RoutingControlState.Off : RoutingControlState.On
},
new UpdateRoutingControlStateEntry()
{
RoutingControlArn = "arn:aws:route53-recovery-control::Account:controlpanel/data/routingcontrol/data",
RoutingControlState = getRoutingControlStateResponseEast.RoutingControlState == RoutingControlState.On ? RoutingControlState.Off : RoutingControlState.On
}
};
UpdateRoutingControlStatesResponse response = await client.UpdateRoutingControlStatesAsync(request);
if (response.HttpStatusCode == HttpStatusCode.OK)
{
break;
}
}
When this code executes I get this error when it tries to get the control state: The requested name is valid, but no data of the requested type was found.
I see in the java example you can set the region and the data plane url endpoint, but I don't see the equivalent in .net.
https://docs.aws.amazon.com/r53recovery/latest/dg/example_route53-recovery-cluster_UpdateRoutingControlState_section.html
This works when I use the cli which I can also set the region and url endpoint.
https://docs.aws.amazon.com/r53recovery/latest/dg/getting-started-cli-routing.control-state.html
What am I doing wrong here?
There is a solution to this question here: https://github.com/aws/aws-sdk-net/issues/1978.
Essentially use the ServiceURL on the configuration object and add a trailing / to the endpoint url.
AmazonRoute53RecoveryClusterConfig clusterRecoveryConfig = new AmazonRoute53RecoveryClusterConfig();
clusterRecoveryConfig.ServiceURL = $"{clusterEndpoint.Endpoint}/";
AmazonRoute53RecoveryClusterClient client = new AmazonRoute53RecoveryClusterClient(_awsCredentials, clusterRecoveryConfig);

Error protecting file using MIP SDK in service/daemon application

can someone help me with the following issue?
Scenario. I have a Windows Service running on an Azure VM. Service receives files, modifies them in some way (let's assume that it adds custom properties to Word files) and uses MIP SDK to protect them with template ID.
Issue. IFileHandler.SetProtection(string)+CommitAsync(...) fails with the following exception:
One or more errors occurred. ServiceDiscoveryHelper::GetServiceDetails - Cannot compute domain: license domains, identity, and cloud endpoint base URL are all empty, correlationId:[9add32ba-0cb7-4d31-b9d8-0000b7c694a4]
Other info
RemoveProtection()+CommitAsync(...) work fine.
I registered application in Azure Active Directory tenant.
Generated secret: <CLIENT_SECRET>.
Granted the following permissions
https://api.mipwebservice.com/InformationProtectionPolicy.Read.All
https://psor.o365syncservice.com/UnifiedPolicy.Tenant.Read
https://aadrm.com/Content.SuperUser
https://aadrm.com/Content.Writer
https://aadrm.com/Content.DelegatedWriter
https://aadrm.com/Content.DelegatedReader
IAuthDelegate implementation
uses ADAL to get access token using client_credentials authentication flow, because there is no interacting user (my app is service).
I do not whether I have to use identity parameter in client_credentials flow.
Main Code Snippet
MIP.Initialize(MipComponent.File);
var appInfo = new ApplicationInfo{
ApplicationId = ConfigurationManager.AppSettings["AppPrincipalId"],
ApplicationName = "App name",
ApplicationVersion = "1.0.0",
};
var authDelegate = new AuthDelegateImplementation(appInfo);
var fileProfileSettings = new FileProfileSettings("mip_data", false,
authDelegate, new ConsentDelegateImplementation(), appInfo, LogLevel.Trace);
var fileProfile = MIP.LoadFileProfileAsync(fileProfileSettings).Result;
var engineSettings = new FileEngineSettings("engine-id", "", "en-US"){
Identity = new Identity($"{appInfo.ApplicationId}#<TENANT-NAME>"){
DelegatedEmail = "<OWNER>#<TENANT-NAME>",
},
};
var fileEngine = fileProfile.AddEngineAsync(engineSettings).Result;
var fileHandler = fileEngine.CreateFileHandlerAsync("c:\\sample.docx", "0", true).Result;
fileHandler.SetProtection(new ProtectionDescriptor("<TEMPLATE-ID>"));
var success = fileHandler.CommitAsync("c:\\encrypted.docx").Result;
AuthDelegateImplementation
public string AcquireToken(Identity identity, string authority, string resource)
var authContext = new AuthenticationContext(authority + "/" + "<TENANT_ID>");
var clientCredential = new ClientCredential("<CLENT_ID>", "<CLIENT_SECRET>");
var res = await authContext.AcquireTokenAsync(resource, clientCredential);
return res.AccessToken;
}
ConsentDelegateImplementation
public class ConsentDelegateImplementation : IConsentDelegate {
public Consent GetUserConsent(string url) {
return Consent.Accept;
}
}
It seams that after testing MIP's local persistent state (see FileProfileSettings.Path property when UseInMemoryStorage is flase) was corrupted. After removing "mip_data" folder issue disappeared.

Update wiki page of tfs by calling rest-api

I want to update an already existing wiki page of tfs by using this document:
https://learn.microsoft.com/de-de/rest/api/azure/devops/wiki/pages/create%20or%20update?view=azure-devops-rest-4.1
Creating a new wiki-page (with content) is no problem. That is working fine.
But I want to edit an existing one. The tfs-documentation says that the only difference in API call is to use an "If-Match"-header (see section Request Header).
Here I have 3 situations:
Using no "If-Match"-Header or an empty: Get a "412 Precondition Failed" error.
Using a "If-Match"-Header with random value: Get a "400 Bad Request" error.
Using a "If-Match"-Header with exactly 40 characters (like the version-hash of the page-revision (e.g. '09f62be600a3b6d36d21b294dbb00921a5ba03ec')): Again "412 Precondition Failed" error.
I think the revision-hash (40 characters) should be a good way because the error message on non-40-chars returns the 400-error.
But it did not work? Has anyone an idea which id tfs is wanting? I used Postman and C# to update by API. Below you can see my example code:
var handler = new HttpClientHandler()
{
UseDefaultCredentials = true,
UseProxy = false,
};
var client = new HttpClient(handler);
client.BaseAddress = new Uri(".../pages/pagename" + "?api-version=4.1");
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
var putContent = new StringContent("{ \"content\": \"New content for page\" }", Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.TryAddWithoutValidation("If-Match", "09f62be600a3b6d36d21b294dbb00921a5ba03ec");
var responseTask = client.PutAsync(client.BaseAddress, putContent);
var result = responseTask.Result;
var content = result.Content.ReadAsStringAsync().Result;
var code = result.StatusCode;
var body = content;
According to the Create or Update Wiki API, if we want to edit the wiki page,If-Match header is required. The value of If-Matchth is the wiki page ETag.
ETags can also be used for optimistic concurrency control, as a way to help prevent simultaneous updates of a resource from overwriting each other
so we need to get the wiki Etag before update. Please have a try to change the code as following:
var baseUrl = "xxxxx";
var handler = new HttpClientHandler()
{
UseDefaultCredentials = true,
UseProxy = false,
};
var client = new HttpClient(handler)
{
BaseAddress = new Uri(baseUrl)
};
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "YourToken");
var getResult = client.GetAsync(baseUrl).Result;
var etag = getResult.Headers.GetValues("ETag");
var putContent = new StringContent("{ \"content\": \"New content for page\" }", Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.TryAddWithoutValidation("If-Match", etag);
var responseTask = client.PutAsync(client.BaseAddress, putContent);
var result = responseTask.Result;
var content = result.Content.ReadAsStringAsync().Result;
Test Result:

How can I read User Entitlements using REST Web Api for VSTS

How can I read User Entitlements using REST Web Api for VSTS?
Currently my code is like this but not getting result.
var accountUriString = "https://app.vssps.visualstudio.com/";
Uri accountUri = new Uri(accountUriString);
LicensingHttpClient licensingHttpClient = new LicensingHttpClient(accountUri, vssCredentials);
Task<AccountEntitlement> accountEntitlementAsync = licensingHttpClient.GetAccountEntitlementAsync();
var accountEntitlement = accountEntitlementAsync.Result;
var license = accountEntitlement.License;
Try the code below:
String collectionUri = "https://{account}.visualstudio.com";
VssCredentials creds = new VssClientCredentials();
creds.Storage = new VssClientCredentialStorage();
VssConnection connection = new VssConnection(new Uri(collectionUri), creds);
var licensingHttpClient = connection.GetClient<LicensingHttpClient>();
var accountEntitlement = licensingHttpClient.GetAccountEntitlementAsync().Result;
var license = accountEntitlement.License;

How create bug work item in visual studio online from wpf app or some other web app?

I have a bugs list managed in a WPF app. I would like to create the bug in the VSO work item. Is there an API available to create work items like bug or task in Visual Studio Online?
Yes, there has the REST API to create a work item. The example code as:
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Newtonsoft.Json;
...
public void CreateBug()
{
string _personalAccessToken = "your personal access token";
string _credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", _personalAccessToken)));
Object[] patchDocument = new Object[4];
patchDocument[0] = new { op = "add", path = "/fields/System.Title", value = "Authorization Errors" };
patchDocument[1] = new { op = "add", path = "/fields/Microsoft.VSTS.TCM.ReproSteps", value = "Our authorization logic needs to allow for users with Microsoft accounts (formerly Live Ids) - http://msdn.microsoft.com/en-us/library/live/hh826547.aspx" };
patchDocument[2] = new { op = "add", path = "/fields/Microsoft.VSTS.Common.Priority", value = "1" };
patchDocument[3] = new { op = "add", path = "/fields/Microsoft.VSTS.Common.Severity", value = "2 - High" };
//use the httpclient
using (var client = new HttpClient())
{
//set our headers
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", _credentials);
//serialize the fields array into a json string
var patchValue = new StringContent(JsonConvert.SerializeObject(patchDocument), Encoding.UTF8, "application/json-patch+json");
var method = new HttpMethod("PATCH");
var request = new HttpRequestMessage(method, "https://accountname.visualstudio.com/fabrikam/_apis/wit/workitems/$Bug?api-version=2.2") { Content = patchValue };
var response = client.SendAsync(request).Result;
//if the response is successfull, set the result to the workitem object
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
}
}
}
More details, you can refer create bug.