CRM 2016 api unauthorized access - wcf

I wrote this code to connect to CRM on premise 2016 and retrieve some data.
Here it's
var credentials = new NetworkCredential("username", "password?", "domain");
var client = new HttpClient(new HttpClientHandler() { Credentials = credentials })
{
BaseAddress = new Uri("https://xxxtestenv.elluciancrmrecruit.com/api/data/v8.0/")
};
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = client.GetAsync("datatel_events?$orderby=datatel_eventname").Result;
if (response.IsSuccessStatusCode)
{
var yourcustomobjects = response.Content.ReadAsStringAsync();
}
but I get this error
response {StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
REQ_ID: b685b007-199b-4a4a-85cc-3a29684e5588
Date: Thu, 22 Sep 2016 19:27:35 GMT
Server: Microsoft-IIS/8.5
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Connection: keep-alive
Content-Length: 49
Content-Type: text/plain
}} System.Net.Http.HttpResponseMessage
Any suggestions?

Try using below code to connect to MS CRM on premise.
string strOrganizationUri = "https://{your domain}/XRMServices/2011/Organization.svc";
string strUserName = "{your domain username}";
string strPassword = "{your domain password}";
var organizationUriIFD = new Uri(strOrganizationUri);
var credentials = new ClientCredentials();
credentials.UserName.UserName = strUserName;
credentials.UserName.Password = strPassword;
IServiceConfiguration<IOrganizationService> config = ServiceConfigurationFactory.CreateConfiguration<IOrganizationService>(organizationUriIFD);
IOrganizationService service;
using (var serviceProxy = new OrganizationServiceProxy(config, credentials))
{
// This statement is required to enable early-bound type support.
serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());
service = serviceProxy;
}
// Get the ID's of the current user and business unit.
var who = new WhoAmIRequest();
//retreive user data from the server.
var whoResponse = (WhoAmIResponse)service.Execute(who);

Related

CKEDITOR File Upload Bad Request 400 Error

I am using ckEditor with the file browser, filemanager plugin in it. What i am trying to achieve when i configure the CKeditor I am able to browse the file in a certain folder .. but when i try to upload the file through it I am getting an error of 400 Bad Request may be there is something which I need to do ?
Following is my code
[HttpPost]
CKEDITOR.replace('content_editor',{
customConfig: '/assets/back/dist/plugins/ckeditor/config.js',
"imageBrowser_listUrl" : "/webmaster/files/browser"
});
CKEDITOR.on('fileUploadRequest', function (evt) {
var fileLoader = evt.data.fileLoader,
formData = new FormData(),
xhr = fileLoader.xhr;
xhr.open( 'PUT', fileLoader.uploadUrl, true );
formData.append( 'upload', fileLoader.file, fileLoader.fileName );
fileLoader.xhr.send( formData );
// Prevented the default behavior.
evt.stop();
} );
Request Handler C# ASP.NET CORE 3.1
public async Task<IActionResult> UploadFromEditor([FromForm]IFormFile upload)
{
if (upload.Length <= 0) return null;
if (!upload.IsImage())
{
var NotImageMessage = "please choose a picture";
dynamic NotImage = JsonConvert.DeserializeObject("{ 'uploaded': 0, 'error': { 'message': \"" + NotImageMessage + "\"}}");
return Json(NotImage);
}
var fileName = Guid.NewGuid() + Path.GetExtension(upload.FileName).ToLower();
Image image = Image.FromStream(upload.OpenReadStream());
int width = image.Width;
int height = image.Height;
if ((width > 750) || (height > 500))
{
var DimensionErrorMessage = "Custom Message for error";
dynamic stuff = JsonConvert.DeserializeObject("{ 'uploaded': 0, 'error': { 'message': \"" + DimensionErrorMessage + "\"}}");
return Json(stuff);
}
if (upload.Length > 500 * 1024)
{
var LengthErrorMessage = "Custom Message for error";
dynamic stuff = JsonConvert.DeserializeObject("{ 'uploaded': 0, 'error': { 'message': \"" + LengthErrorMessage + "\"}}");
return Json(stuff);
}
var path = Path.Combine(
Directory.GetCurrentDirectory(), "wwwroot/uploads/images/conten_images",
fileName);
using (var stream = new FileStream(path, FileMode.Create))
{
upload.CopyTo(stream);
}
var url = $"{"/uploads/images/CKEditorImages/"}{fileName}";
var successMessage = "image is uploaded successfully";
dynamic success = await Task.Run(() => JsonConvert.DeserializeObject("{ 'uploaded': 1,'fileName': \"" + fileName + "\",'url': \"" + url + "\", 'error': { 'message': \"" + successMessage + "\"}}"));
return Json(success);
}
Extra Plugins code :
CKEDITOR.editorConfig = function( config ) {
config.filebrowserBrowseUrl = '/assets/back/dist/ckeditor/plugins/imagebrowser/browser/browser.html'
config.filebrowserUploadUrl = '/webmaster/files/UploadFromEditor';
config.extraPlugins = 'filetools';
config.extraPlugins = 'uploadimage';
config.extraPlugins = 'popup';
config.extraPlugins = 'imagebrowser';
config.filebrowserUploadMethod = 'xhr';
};
Please help me out here
here are the headers :
XHRPOSThttps://localhost:5001/webmaster/files/UploadFromEditor
[HTTP/2 400 Bad Request 73ms]
POST
https://localhost:5001/webmaster/files/UploadFromEditor
Status400
Bad Request
VersionHTTP/2
Transferred85.50 KB (0 B size)
content-length
0
date
Tue, 03 Nov 2020 09:13:50 GMT
server
Kestrel
X-Firefox-Spdy
h2
Accept
*/*
Accept-Encoding
gzip, deflate, br
Accept-Language
en-US,en;q=0.5
Connection
keep-alive
Content-Length
86268
Content-Type
multipart/form-data; boundary=---------------------------1063707225330149515660008029
Cookie
.AspNetCore.Session=CfDJ8ERqQf6e11lCnNAhOo0wjyavEQJqEJ7gsv1MXMI4QwPk9Px8mznruNuZcxnmuYGnGjs1GtOWQI4DVCXYKd%2FRbNNo62%2FtopzHy%2FxaW87rvNE13QikL84JT0m32Ie1LWSZR3AkxYAE5p4U7TEpN5FccezCSMDeUR9geLW3lSjFIJD4; .AspNetCore.Antiforgery.J7MIrShXchg=CfDJ8ERqQf6e11lCnNAhOo0wjyYadzIaShP7Nt-bl6orx5lTMtnVoGxw8noimjE32qvhp_f96p2Hx4_zK8hzdRIz12615ZdyisBTz6X9HPA39cgIvRTjmWmrWNcLlm4S2MvPAQrG9hofg1ANinWAOwKIyXc; ckCsrfToken=8qZ4KEfRjaBWRmI6coRoRbJrZd8DgYG18gAz86eN; .AspNetCore.Antiforgery.XfkU3LYWHPY=CfDJ8NfGIpF9PVtNgLP3wXt3ZoscmmPZ8ZskVSbYiI69p4lPZYB3mt9mFEqRuOV0Ajfi2f8NNbjcyEHtfta7RlEHTBhXdRfPonXD1sN2EIS2BvcjZCrN8sJXN4UMo_JlolirVt3VIcCTm-wGAtIzGq0150w
Host
localhost:5001
Origin
https://localhost:5001
Referer
https://localhost:5001/webmaster/News/Create
TE
Trailers
User-Agent
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0
X-Requested-With
XMLHttpRequest
Cookie “.AspNetCore.Antiforgery.XfkU3LYWHPY” will be soon treated as cross-site cookie against “https://localhost:5001/webmaster/files/UploadFromEditor” because the scheme does not match. UploadFromEditor
Source map error: Error: request failed with status 404
Resource URL: https://localhost:5001/assets/back/dist/bootstrap/js/bootstrap.min.js
Source Map URL: bootstrap.min.js.map
Based on the details about your test request, it seems that you configured and enabled antiforgery token validation. If JavaScript client not set/include the token in request, which would cause 400 Bad Request error.
To fix it, as I mentioned in comment, we can apply IgnoreAntiforgeryToken Attribute to action method UploadFromEditor to skip antiforgery token validation.
Or set the token in request header to make the request can pass antiforgery token validation.
https://learn.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-3.1#javascript

how to send Content-Disposition: form-data; name="name" in correct way when call post api from C# to avoid statuserror 500

public async Task<T> PostFrom<T>(string baseAddress, string url, string requestbody)
{
T obj = default(T);
//Create the Uri string
string request = baseAddress + url;
WriteLog(request + " : " + "start");
try
{
//Create the Uri
var urirequest = new Uri(request);
//define MultipartFormDataContent
var multipart = new MultipartFormDataContent();
//Add Content-Type
multipart.Headers.Remove("Content-Type");
multipart.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundary=" + financialAuth.Value.ContentType.boundary);
//Add AuthToken
multipart.Headers.Add("AuthToken", financialAuth.Value.AuthToken);
//start adding the Content-Disposition which i have 3 of them
//1st Content-Disposition form-data; name="SearchCriteria" "requestbody" is the json
if (!string.IsNullOrEmpty(requestbody))
{
var requestbodyContent = new StringContent(JsonConvert.SerializeObject(requestbody));
requestbodyContent.Headers.Add("Content-Disposition", "form-data; name=\"SearchCriteria\"");
multipart.Add(requestbodyContent, "SearchCriteria");
}
//2nd Content-Disposition form-data; name="Secret" "financialAuth.Value.Secret" is the string
var secretContent = new StringContent(financialAuth.Value.Secret);
secretContent.Headers.Add("Content-Disposition", "form-data; name=\"Secret\"");
multipart.Add(secretContent, "Secret");
//3rd Content-Disposition form-data; name="AppID" "financialAuth.Value.AppID" is the string
var appIdContent = new StringContent(financialAuth.Value.AppID);
appIdContent.Headers.Add("Content-Disposition", "form-data; name=\"AppID\"");
multipart.Add(appIdContent, "AppID");
//define the HttpRequestMessage of type post
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, urirequest);
//assign the multipart of httpRequestMessage.Content
httpRequestMessage.Content = multipart;
//assign the urirequest of httpClient.BaseAddress
client.BaseAddress = urirequest;
WriteLog("start url" + request);
/* Here when I call the post web api I'm getting below error:
{{StatusCode: 500, ReasonPhrase: 'Internal Server Error', Version: 1.1, Content: System.Net.Http.HttpConnection+HttpConnectionResponseContent,
Headers: {
Cache-Control: no-cache
Pragma: no-cache
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type,authtoken
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Date: Tue, 26 Feb 2019 14:59:51 GMT
Content-Type: application/json; charset=utf-8
Expires: -1
Content-Length: 36
}}
*/
HttpResponseMessage response = await client.SendAsync(httpRequestMessage).ConfigureAwait(false);
WriteLog("END url" + request);
if (response.IsSuccessStatusCode)
{
WriteLog(request + " : " + "Begin Result");
string result = await response.Content.ReadAsStringAsync();
obj = JsonConvert.DeserializeObject<T>(result);
WriteLog(request + " : " + "End Result");
}
}
catch (Exception ex)
{
WriteLog(request + " " + ex.Message);
}
return obj;
}
I just solved the error by commenting the below code:
// Add Content-Type
multipart.Headers.Remove("Content-Type");
multipart.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundary=" + financialAuth.Value.ContentType.boundary);
It seems the content type will be created automatically by MultipartFormDataContent.
Thanks for looking into my issue.

create user accounts in office 365 using c#.net code dynamically

I want a sample application in c#.net which can create users in Office 365 using Microsoft API .
I wish to do it in code, not using Powershell.
You can use the Microsoft Graph API - Create User:
Register a Native Client App on Azure AD, assign the "Microsoft Graph" > "Read and Write Directory Data" permission.
string authority = "https://login.windows.net/yourdomain.onmicrosoft.com";
string clientId = "{app_client_id}";
Uri redirectUri = new Uri("http://localhost");
string resourceUrl = "https://graph.microsoft.com";
HttpClient client = new HttpClient();
AuthenticationContext authenticationContext = new AuthenticationContext(authority, false);
AuthenticationResult authenticationResult = authenticationContext.AcquireToken(resourceUrl,
clientId, redirectUri, PromptBehavior.Always);
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + authenticationResult.AccessToken);
string content = #"{
'accountEnabled': true,
'displayName': 'testuser',
'mailNickname': 'test',
'passwordProfile': {
'forceChangePasswordNextSignIn': true,
'password': 'pass#wd12345'
},
'userPrincipalName': 'testuser#yourdomain.onmicrosoft.com'
}";
var httpContent = new StringContent(content, Encoding.GetEncoding("utf-8"), "application/json");
var response = client.PostAsync("https://graph.microsoft.com/v1.0/users", httpContent).Result;
Console.WriteLine(response.Content.ReadAsStringAsync().Result);

Dynamics CRM Web Api Function: Illegal characters in path when using encodeURIComponent

I'm trying to use the Search Function (https://msdn.microsoft.com/en-us/library/mt608029.aspx) via the Dynamics CRM 2016 Web API. This is my code:
var start = new Date(2016, 2, 1, 17, 0, 0);
var end = new Date(2016, 2, 10, 18, 0, 0);
var request = new Object();
request.AppointmentRequest = new Object();
request.AppointmentRequest.SearchWindowStart = start.toISOString();
request.AppointmentRequest.SearchWindowEnd = end.toISOString();
request.AppointmentRequest.ServiceId = "5f3b6e7f-48c0-e511-80d7-d89d67631c44";
request.AppointmentRequest.Direction = 0;
request.AppointmentRequest.NumberOfResults = 10;
request.AppointmentRequest.UserTimeZone = 1;
var req = new XMLHttpRequest()
req.open("GET", clientUrl + "/api/data/v8.0/Search(" + encodeURIComponent( JSON.stringify(request) ) +")", true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
if (req.readyState == 4 && req.status == 200) {
alert(req.responseText);
}
else {
alert(req.response);
}
};
req.send();
When I initially tried this using CRM Online I received the following error:
"An error has occurred.
Try this action again. If the problem continues, check the Microsoft Dynamics >CRM Community for solutions or contact your organization's Microsoft >Dynamics CRM Administrator. Finally, you can contact Microsoft Support."
When I try this with an On-Premise deployment with DevErrors="On" in the web.config, I see the following error in the Event Viewer:
Exception information:
Exception type: HttpException
Exception message: A potentially dangerous Request.Path value was detected >from the client (:).
at System.Web.HttpRequest.ValidateInputIfRequiredByConfig()
at System.Web.HttpApplication.PipelineStepManager.ValidateHelper(HttpContext >context)
Request information:
Request URL: http://win-0e5dfqgqorm:444/ORG/api/data/v8.0/Search({"AppointmentRequest":{"SearchWindowStart":"2016-03-01T17:00:00.000Z","SearchWindowEnd":"2016-03-10T18:00:00.000Z","ServiceId":"5f3b6e7f-48c0-e511-80d7-d89d67631c44","Direction":0,"NumberOfResults":10,"UserTimeZone":1}})
Request path: /SHUDEV/api/data/v8.0/Search({"AppointmentRequest":{"SearchWindowStart":"2016-03-01T17:00:00.000Z","SearchWindowEnd":"2016-03-10T18:00:00.000Z","ServiceId":"5f3b6e7f-48c0-e511-80d7-d89d67631c44","Direction":0,"NumberOfResults":10,"UserTimeZone":1}})
The JSON object is encoded so I'm not sure why it's detected illegal characters. The SDK documentation for the Web Api is light and doesn't go into too much detail as to how to pass a ComplexType to a Web Api function, has anyone seen this issue before/managed to pass a ComplexType to a Web Api function?
Thanks in advance.
I managed to resolve this issue. The key is to pass the JSON object in as a query parameter:
var request = new Object();
request.SearchWindowStart = start.toISOString();
request.SearchWindowEnd = end.toISOString();
request.ServiceId = "5f3b6e7f-48c0-e511-80d7-d89d67631c44";
request.Direction = '0';
request.NumberOfResults = 10;
request.UserTimeZoneCode = 1;
var req = new XMLHttpRequest()
req.open("GET", clientUrl + "/api/data/v8.0/Search(AppointmentRequest=#request)?#request=" + JSON.stringify(request) , true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
if (req.readyState == 4 && req.status == 200) {
alert(req.responseText);
}
else {
alert(req.response);
}
};
req.send();
This is documented in the SDK: https://msdn.microsoft.com/en-us/library/gg309638.aspx.
Hope this helps anyone who runs into a similar issue.

Swift - 8tracks.com API POST json data fails (422) everytime

I'm trying to talk with 8tracks open API in Swift iOS app. I need to make POST authorization request to http://8tracks.com/sessions.jsonwith AFNetworking but everytime I get 422 Unprocessable Entity error..
I tried this endpoint on the web and it works fine. Here is code that I'm using (subclassing AFHTTPSessionManager):
init() {
super.init()
self.responseSerializer = AFJSONResponseSerializer()
self.requestSerializer = AFJSONRequestSerializer()
self.requestSerializer.setValue(API_KEY, forHTTPHeaderField: "X-Api-Key")
self.requestSerializer.setValue("3", forHTTPHeaderField: "X-Api-Version")
}
func login(username: String, password: String, success: (NSURLSessionDataTask!, AnyObject!) -> Void, failure: ((NSURLSessionDataTask!, NSError!) -> Void)?) {
let credentials = ["username": username, "password": password] as Dictionary
self.POST(
API_URL.stringByAppendingString("/sessions.json"),
parameters: credentials,
success: success,
failure: failure
)
}
Error looks as follows:
{ URL: http://8tracks.com/sessions.json } { status code: 422, headers {
"Accept-Ranges" = bytes;
"Access-Control-Allow-Origin" = "*";
Age = 0;
"Cache-Control" = "max-age=0, private, must-revalidate";
Connection = "keep-alive";
"Content-Length" = 125;
"Content-Type" = "application/json; charset=utf-8";
Date = "Wed, 25 Jun 2014 19:29:12 GMT";
Server = "nginx/1.4.3";
Status = "422 Unprocessable Entity";
Via = "1.1 varnish";
"X-Action" = "sessions/create";
"X-Backend" = rails;
"X-Cache" = MISS;
"X-Data-Request" = 1;
"X-Request-Id" = 3040c8bf79936b27075731f634bfd534;
"X-Requests-Left" = 99;
"X-Runtime" = "0.257240";
"X-UA-Compatible" = "IE=Edge,chrome=1";
} }, NSLocalizedDescription=Request failed: client error (422),
NSErrorFailingURLKey=http://8tracks.com/sessions.json}
It might have something to do with subclass AFHTTPSessionManager without a baseURL. I've tested the following code and it works.
let path = "/sessions.json"
let params = ["login": login, "password": password, "api_version": "3"]
let success = {(task: NSURLSessionDataTask!, response: AnyObject!) -> Void in
println(response)
}
let failure = {(task: NSURLSessionDataTask!, error: NSError!) -> Void in
println(error)
}
var client = AFHTTPSessionManager(baseURL: NSURL(string: "https://8tracks.com"))
client.POST(path, parameters: params, success: success, failure: failure)