I am trying to download a file content from SOAP API which is imported as an wsdl into my .net core project. I can see the response in the fiddler that file contents are coming back from API but in my .net code it is blank. Every other field in the response is coming back fine and it is just the content of the file getting striped out from response.
Below is the code to download:
BasicHttpBinding basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.None);
basicHttpBinding.MaxBufferSize = 2147483647;
basicHttpBinding.MaxBufferPoolSize = 2147483647;
basicHttpBinding.MaxReceivedMessageSize = 2147483647;
basicHttpBinding.ReaderQuotas.MaxStringContentLength = 2147483647;
basicHttpBinding.ReaderQuotas.MaxArrayLength = 2147483647;
basicHttpBinding.ReaderQuotas.MaxDepth = 32;
basicHttpBinding.ReaderQuotas.MaxBytesPerRead = 2147483647;
var wcfHostUri = new Uri(esbServiceOptions?.DocumentumServiceHost);
var endpoint = new Uri(wcfHostUri, esbServiceOptions?.RACQServiceFolderUrl);
var endpointAddress = new EndpointAddress(endpoint);
var client = new RACQ.PC.DocumentumService.RACQServicePortClient(basicHttpBinding, endpointAddress);
using (new OperationContextScope(client.InnerChannel))
{
var identitiesHeader = new ServiceContextHeader();
OperationContext.Current.OutgoingMessageHeaders.Add(identitiesHeader);
var document = client.retrieveDocumentAsync(new PC.DocumentumService.ObjectIdentitySet()
{
Identities = new[]
{
new ObjectIdentity
{
repositoryName = esbServiceOptions.RepositoryName,
valueType = ObjectIdentityType.OBJECT_ID,
valueTypeSpecified = true,
Item = new ObjectId
{
id = documentId
}
}
}
}, new OperationOptions()
{
Profiles = new Profile[]
{
new ContentTransferProfile
{
transferMode = ContentTransferMode.BASE64,
transferModeSpecified = true
},
new ContentProfile
{
urlReturnPolicy = UrlReturnPolicy.NEVER,
urlReturnPolicySpecified = true,
renditionTypeFilter = RenditionTypeFilter.ANY,
renditionTypeFilterSpecified = true,
pageModifierFilter = PageModifierFilter.ANY,
pageModifierFilterSpecified = true,
pageFilter = PageFilter.ANY,
pageFilterSpecified = true,
formatFilter = FormatFilter.ANY,
formatFilterSpecified = true
}
}
}, esbServiceOptions.DocumentUsername).GetAwaiter().GetResult();//Result;
var content = (BinaryContent)document.#return.DataObjects.First().Contents.First();
return content.Value; //this is null
The #content.Value is null in the above code. The below is that is in the fiddler you can clearly see that file is coming back for the same request I am capturing:
Related
I generated a Service Reference from url https://portal.shipsea.ru/services/ShipService?wsdl with Visual Studio 2022.
I tried to invoke some method of generated client.
Here is my code:
var binding = new BasicHttpsBinding();
binding.MaxReceivedMessageSize = 2147483647;
var endpointAddress = new EndpointAddress("https://portal.shipsea.ru:443/services/ShipService");
using var client = new ShipServiceClient(binding, endpointAddress);
client.ClientCredentials.Windows.ClientCredential.UserName = "******";
client.ClientCredentials.Windows.ClientCredential.Password = "******";
var responce = client
.getShipPositionsAsync(
new ShipPositionRequest
{
start = 0,
limit = 1000,
minLatitude = 0,
minLongitude = 0,
maxLatitude = 0,
maxLongitude = 0,
minReceiveDate = DateTime.Now,
maxReceiveDate = DateTime.Now.AddDays(-30)
})
When making the call, I get an exception:
System.ServiceModel.FaultException: A required header representing a Message Addressing Property is not present
Is there something wrong with the client generation? Or how to add the missing header when called?
I am new to amazone SES and trying to set up my .net core API to send emails using SES. Here is code I`m using to send emails:
SendEmailRequest request = new SendEmailRequest();
request.FromEmailAddress = "email#outlook.com";//verified
//request.
Destination destination= new Destination();
destination.ToAddresses = new List<string> {"some verified email"};
request.Destination = destination;
EmailContent content = new EmailContent();
content.Simple = new Message
{
Body = new Body
{
Html = new Content
{
Data = $#"<html>
//here is some code
</html>"
}
},
Subject = new Content{
Data = "some subject"
}
};
request.Content = content;
request.FromEmailAddressIdentityArn = senderArn;
var status = await _sesClient.SendEmailAsync(request);
This code gives me such error: The From ARN <arn:aws:ses:eu-central-1:xxxxxxxxxxxxxx> is not a valid SES identity.
On AWS console emails are verified:
Any ideas what I`m doing wrong?
Here is .NET Code that does work. The sender has to be verified in SES. See https://docs.aws.amazon.com/ses/latest/dg/creating-identities.html.
public async void SendMessage(string text, string toAddress)
{
var sesClient = new AmazonSimpleEmailServiceClient(RegionEndpoint.USWest2);
var sender = "scmacdon#amazon.com";
var emailList = new List<string>();
emailList.Add(toAddress);
var destination = new Destination
{
ToAddresses = emailList
};
var content = new Content
{
Data = text
};
var sub = new Content
{
Data = "Amazon Rekognition Report"
};
var body = new Body
{
Text = content
};
var message = new Message
{
Subject = sub,
Body = body
};
var request = new SendEmailRequest
{
Message = message,
Destination = destination,
Source = sender
};
try
{
await sesClient.SendEmailAsync(request);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Update
Make sure you are using this version.
I'm getting an error:
A security error was encountered when verifying the message
Https is expected when I somehow overcome this error. But I have to use Http.
EndpointAddress address2 = new EndpointAddress("http://xx.xx.xxxx/ws/test?wsdl");
FactoryWebServiceClient client = new FactoryWebServiceClient();
client.Endpoint.Address = address2;
if (client.ClientCredentials != null)
{
client.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential("username","password");
client.ClientCredentials.UserName.UserName = "username";
client.ClientCredentials.UserName.Password = "password";
}
XmlDocument doc = new XmlDocument();
doc.Load("C:\\...\\test.xml");
byte[] bytes = Encoding.Default.GetBytes(doc.OuterXml);
var request2 = new factoryWSUpdateData
{
BeanXml = bytes,
Period = 1,
InputType = "xml",
OutputType = "json2",
CodeTemplate = 1
};
var result = client.create(request2);
I'm trying to create a web app (hosted on Azure) for clients to be able to submit work items to our team services page. Basically a support ticket page so they don't have to call to explain their backlog all the time.
Below is the class and method i've made to create work items, following Microsoft's sample code, with some obvious changes for privacy reasons. This method is triggered by a button click, and so far I cannot get it to create any work items.
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Newtonsoft.Json;
namespace customapp
{
public class CreateWorkItem
{
public void CreateWorkItemMethod()
{
string personalAccessToken = "xxxxxxxxx";
string credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "xxx", personalAccessToken)));
Object[] patchDocument = new Object[1];
patchDocument[0] = new { op = "add", path = "/fields/System.Title", value = "Test" };
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
var patchValue = new StringContent(JsonConvert.SerializeObject(patchDocument), Encoding.UTF8, "application/json-patch+json");
var method = new HttpMethod("PATCH");
var request = new HttpRequestMessage(method, "https://example.visualstudio.com/exampleproject/_apis/wit/workitems/$Support&20Ticket?api-version=1.0") { Content = patchValue };
var response = client.SendAsync(request).Result;
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
}
}}}}
In the url for the PATCH I am using the team project's ID (in place of /exampleproject you see below). Our site is set up to have an overall project, let's call it ""Master", and inside is a team project for each client, for example "ClientProject". So basically I want to create a "Support Ticket" work item in Master->ClientProject->Backlog/Board.
Using Master\\areapath instead (not Master\areapath).
Sample body:
[
{
"op": "add",
"path": "/fields/System.Title",
"value": "PBIAPI2"
},
{
"op": "add",
"path": "/fields/System.AreaPath",
"value": "Scrum2015\\SharedArea"
}
]
On the other hand, it’s better to create work item by using VSTS/TFS API with Microsoft Team Foundation Server Extended Client package.
Simple sample code:
var u = new Uri("https://[account].visualstudio.com");
VssCredentials c = new VssCredentials(new Microsoft.VisualStudio.Services.Common.VssBasicCredential(string.Empty, "[personal access token]"));
var connection = new VssConnection(u, c);
var workitemClient = connection.GetClient<WorkItemTrackingHttpClient>();
var workitemtype = "Product Backlog Item";
string teamProjectName = "Scrum2015";
var document = new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchDocument();
document.Add(
new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
{
Path = "/fields/Microsoft.VSTS.Common.Discipline",
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Value = "development"
});
document.Add(
new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
{
Path = "/fields/System.Title",
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Value = string.Format("{0} {1}", "RESTAPI", 6)
});
document.Add(new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
{
Path = "/fields/System.AreaPath",
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Value =string.Format("{0}\\{1}",teamProjectName, "SharedArea")
});
document.Add(
new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
{
Path = "/fields/System.AssignedTo",
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Value = "[user account]"
});
document.Add(
new Microsoft.VisualStudio.Services.WebApi.Patch.Json.JsonPatchOperation()
{
Path = "/fields/System.Description",
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Value = "destest"
});
var workitem= workitemClient.CreateWorkItemAsync(document, teamProjectName, workitemtype).Result;
The method must be POST and Uri correct for consume the Api tfs is :
https://dev.azure.com/{organization}/{proyect}/_apis/wit/workitems/${type}?api-version=5.0
Check in :
https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/work%20items/create?view=azure-devops-rest-5.0
The next code function for me.
static void Main(string[] args)
{
CreateWorkItem();
}
public static void CreateWorkItem()
{
string _tokenAccess = "************"; //Click in security and get Token and give full access https://azure.microsoft.com/en-us/services/devops/
string type = "Bug";
string organization = "type your organization";
string proyect = "type your proyect";
string _UrlServiceCreate = $"https://dev.azure.com/{organization}/{proyect}/_apis/wit/workitems/${type}?api-version=5.0";
dynamic WorkItem = new List<dynamic>() {
new
{
op = "add",
path = "/fields/System.Title",
value = "Sample Bug test"
}
};
var WorkItemValue = new StringContent(JsonConvert.SerializeObject(WorkItem), Encoding.UTF8, "application/json-patch+json");
var JsonResultWorkItemCreated = HttpPost(_UrlServiceCreate, _tokenAccess, WorkItemValue);
}
public static string HttpPost(string urlService, string token, StringContent postValue)
{
try
{
string request = string.Empty;
using (HttpClient httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", token))));
using (HttpRequestMessage httpRequestMessage = new HttpRequestMessage(new HttpMethod("POST"), urlService) { Content = postValue })
{
var httpResponseMessage = httpClient.SendAsync(httpRequestMessage).Result;
if (httpResponseMessage.IsSuccessStatusCode)
request = httpResponseMessage.Content.ReadAsStringAsync().Result;
}
}
return request;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
I have a web application and web api services that authenticate through ADFS. They are contained in the same IIS application, and the web app makes calls back to the web api services without a problem.
I'm now trying to call the same services from a different application, but am having trouble passing the token. I am able to authenticate and retrieve a SAML token with the following code:
var stsEndpoint = "https://MyAdfsServer/adfs/services/trust/13/UsernameMixed";
var reliantPartyUri = "https://MyDomain/AppRoot/";
var factory = new Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannelFactory(
new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
new EndpointAddress(stsEndpoint));
factory.TrustVersion = System.ServiceModel.Security.TrustVersion.WSTrust13;
// Username and Password here...
factory.Credentials.UserName.UserName = #"Domain\UserName";
factory.Credentials.UserName.Password = "Password";
var rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
AppliesTo = new EndpointAddress(reliantPartyUri),
KeyType = KeyTypes.Bearer,
};
var channel = factory.CreateChannel();
var token = channel.Issue(rst) as GenericXmlSecurityToken;
var saml = token.TokenXml.OuterXml;
However, I'm not sure how to pass the saml in to the web api call. I've tried this:
using (var handler = new HttpClientHandler()
{
ClientCertificateOptions = ClientCertificateOption.Automatic,
AllowAutoRedirect = false
})
{
using (var client = new HttpClient(handler))
{
client.BaseAddress = new Uri("https://MyDomain/AppRoot/api/");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SAML", saml);
HttpResponseMessage response = client.GetAsync("MyService/Get/").Result;
// Get the results...
var result = response.Content.ReadAsStringAsync().Result;
var status = response.StatusCode;
}
}
This is returning a status code of 302 and trying to redirect me to the ADFS server for authentication. Is there another way to pass the SAML token to the web api service?
(SET)
string samlString = "blah blah blah";
byte[] bytes = Encoding.UTF8.GetBytes(samlString);
string base64SamlString = Convert.ToBase64String(bytes);
myHttpClient.DefaultRequestHeaders.Add("X-My-Custom-Header", base64SamlString);
(GET)
IEnumerable<string> headerValues = request.Headers.GetValues("X-My-Custom-Header");
if (null != headerValues)
{
var encoding = Encoding.GetEncoding("iso-8859-1");
string samlToken = encoding.GetString(Convert.FromBase64String(headerValues.FirstOrDefault()));
}
When you want to access a resource which is protected via SSO (like ADFS, I assume), I found it easiest to use following approach: Show a WebBrowser element, let user enter credentials, then grab global cookies, and pass them into new HttpClient which performs the actual HTTP operation.
Here a complete code sample which downloads all build statuses from a SAML-protected Jenkins server:
private void Start()
{
var t = new Thread(ThreadProc);
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
}
public async void ThreadProc()
{
try
{
var urlBase = "https://JENKINS/";
var url = urlBase + "job/JOBNAME/api/json?depth=1&tree=lastBuild[timestamp],builds[number,result,timestamp,url,actions[lastBuiltRevision[SHA1,branch[name]],totalCount,failCount,skipCount],building,duration]";
var form = new Form();
var browser = new System.Windows.Forms.WebBrowser();
browser.SetBounds(0, 0, 400, 400);
form.Size = new System.Drawing.Size(400, 400);
form.Controls.AddRange(new Control[] { browser });
form.FormBorderStyle = FormBorderStyle.FixedDialog;
form.StartPosition = FormStartPosition.CenterScreen;
form.MinimizeBox = false;
form.MaximizeBox = false;
// Navigate to base URL. It should internally forward to login form. After logging in, close browser window.
browser.Navigate(urlBase);
form.ShowDialog();
var cookieString = GetGlobalCookies(urlBase);
var cookieContainer = new System.Net.CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = new Uri(urlBase, UriKind.Absolute) })
{
cookieContainer.SetCookies(client.BaseAddress, cookieString);
var response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var responseStream = await response.Content.ReadAsStreamAsync();
using (var reader = new System.IO.StreamReader(responseStream))
{
var responseString = await reader.ReadToEndAsync();
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
[System.Runtime.InteropServices.DllImport("wininet.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]
private static extern bool InternetGetCookieEx(string pchURL, string pchCookieName,
System.Text.StringBuilder pchCookieData, ref uint pcchCookieData, int dwFlags, IntPtr lpReserved);
private const int INTERNET_COOKIE_HTTPONLY = 0x00002000;
public string GetGlobalCookies(string uri)
{
uint uiDataSize = 2048;
var sbCookieData = new System.Text.StringBuilder((int)uiDataSize);
if (InternetGetCookieEx(uri, null, sbCookieData, ref uiDataSize,
INTERNET_COOKIE_HTTPONLY, IntPtr.Zero)
&&
sbCookieData.Length > 0)
{
return sbCookieData.ToString().Replace(";", ",");
}
return null;
}