"404 - File or directory not found" error when logging in to DocuSign API - c#

I am using the code listed below for a c# visual studio project to interface with the DocuSign API. As soon as the code gets to
LoginInformation loginInfo = authApi.Login();
I am getting error message:
404 - File or directory not found.
The resource you are looking for might have been removed, had its name changed, or is temporarily unavailable
Does anyone know why?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Newtonsoft.Json;
using DocuSign.eSign.Api;
using DocuSign.eSign.Model;
using DocuSign.eSign.Client;
namespace CoreRecipes
{
class Program
{
private string INTEGRATOR_KEY = "[key]";
static void Main(string[] args)
{
Program recipes = new Program();
recipes.listDocumentsAndDownloadTest();
Console.Read();
}
public void listDocumentsAndDownloadTest()
{
string username = "[username]";
string password = "[password]";
string envelopeId = "envelopid";
//configureApiClient("www.docusign.net/restapi");
//http"s://demo.docusign.net/restapi"
configureApiClient("https://demo.docusign.net/restpi");
string accountId = loginApi(username, password);
EnvelopesApi envelopesApi = new EnvelopesApi();
EnvelopeDocumentsResult docsList = envelopesApi.ListDocuments(accountId, envelopeId);
Console.WriteLine("EnvelopeDocumentsResult:\n{0}", JsonConvert.SerializeObject(docsList));
int docCount = docsList.EnvelopeDocuments.Count;
string filePath = null;
FileStream fs = null;
for (int i = 0; i < docCount; i++)
{
MemoryStream docStream = (MemoryStream)envelopesApi.GetDocument(accountId, envelopeId, docsList.EnvelopeDocuments[i].DocumentId);
filePath = Path.GetTempPath() + Path.GetRandomFileName() + ".pdf";
fs = new FileStream(filePath, FileMode.Create);
docStream.Seek(0, SeekOrigin.Begin);
docStream.CopyTo(fs);
fs.Close();
Console.WriteLine("Envelope Document {0} has been downloaded to: {1}", i, filePath);
}
}
public void configureApiClient(string basePath)
{
ApiClient apiClient = new ApiClient(basePath);
Configuration.Default.ApiClient = apiClient;
}
public string loginApi(string usr, string pwd)
{
ApiClient apiClient = Configuration.Default.ApiClient;
string authHeader = "{\"Username\":\"" + usr + "\", \"Password\":\"" + pwd + "\", \"IntegratorKey\":\"" + INTEGRATOR_KEY + "\"}";
Configuration.Default.AddDefaultHeader("X-DocuSign-Authentication", authHeader);
string accountId = null;
AuthenticationApi authApi = new AuthenticationApi();
LoginInformation loginInfo = authApi.Login();
foreach (LoginAccount loginAcct in loginInfo.LoginAccounts)
{
if (loginAcct.IsDefault == "true")
{
accountId = loginAcct.AccountId;
break;
}
}
if (accountId == null)
{
accountId = loginInfo.LoginAccounts[0].AccountId;
}
return accountId;
}
}
}

The issue is with this list:
configureApiClient("https://demo.docusign.net/restpi")
There is a typo in it - as identified by going to https://demo.docusign.net/restpi and seeing that it returned a 404.
I suggest changing it to:
configureApiClient("https://demo.docusign.net/restapi")

Related

Code indicating that the "_edgeKey" object is null when the code tries to access it

I have a C# code that connects to a set of APIs and retrieves and displays specific data. Initially, the code was written in a way that heavily depended on Internet Explorer (the user had to be logged in to their account only through IE; otherwise, the application couldn't make a connection to the API). Since the IE expired, the code could no longer connect to the API, so I replaced the cookies with edge cookies. I receive no errors; however, the code is not giving the desire outcome. When I debugged, it looks like the exception of "Error:_edgeKey is null" is being thrown. How can I fix this?
I have created a folder named Controllers which includes StaticStrings.cs, WebAPI.cs, WebNav.cs.
StaticStrings.cs includes the set of APIs
WebAPI.cs includes the following code:
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using WeeklyScheduleModels;
using Newtonsoft.Json;
using System.Net.Http;
using System.Threading.Tasks;
namespace WeeklySchedule.Contollers
{
class WebAPI
{
public string GetNorderTimeExpensebyNo(string norderNo)
{
return "OK";
}
public string GetNorderDbIDfromNo(string norderNo)
{
return "";
}
public async Task<double> GetBookedHours(string subOrderNo)
//public double GetBookedHours(string subOrderNo)
{
using (var edgeCookie = new EdgeCookie())
{
var cookies = edgeCookie.GetCookies(new Uri(StaticStrings.UrlNCert), false);
var cookieString = new StringBuilder();
foreach (var cookie in cookies)
{
cookieString.Append(cookie.Name + "=" + cookie.Value + "; ");
}
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Cookie", cookieString.ToString());
string uri = "";
double totalHours = 0.0;
uri = StaticStrings.NOrderTimeExpenseAPI + subOrderNo;
var response = await client.GetStringAsync(uri);
NCertTimeExpenseMain ntem = JsonConvert.DeserializeObject<NCertTimeExpenseMain>(response);
foreach (OracleHour oh in ntem.oracleHours)
{
totalHours += oh.hours;
}
return totalHours;
}
}
//To get the status of the project from Ncert
public async Task<string> GetOrderStatus(string subOrderNo)
{
using (var edgeCookie = new EdgeCookie())
{
var cookies = edgeCookie.GetCookies(new Uri(StaticStrings.UrlNCert), false);
var cookieString = new StringBuilder();
foreach (var cookie in cookies)
{
cookieString.Append(cookie.Name + "=" + cookie.Value + "; ");
}
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Cookie", cookieString.ToString());
string uri = "";
uri = StaticStrings.OrderStatusAPI + subOrderNo + '?';
var response = await client.GetStringAsync(uri);
RootObject status = JsonConvert.DeserializeObject<RootObject>(response);
string currentstatusofproject = status.statusDescription;
return currentstatusofproject;
}
}
public CustomerList GetCustomerListFromPartialName(string partialName)
{
using (var edgeCookie = new EdgeCookie())
{
var cookies = edgeCookie.GetCookies(new Uri(StaticStrings.UrlNCert), false);
var cookieString = new StringBuilder();
foreach (var cookie in cookies)
{
cookieString.Append(cookie.Name + "=" + cookie.Value + "; ");
}
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Cookie", cookieString.ToString());
string searchStr = StaticStrings.CustomerSearchAPI + partialName + "&%24format=json&%24top=30&%24filter=status%20eq%20%27Active%27&%24count=true";
var response = client.GetStringAsync(searchStr).Result;
CustomerList cl = JsonConvert.DeserializeObject<CustomerList>(response);
return cl;
}
}
public List<FrameAgreement> GetAgreementsFromCustomerId(string customerId)
{
using (var edgeCookie = new EdgeCookie())
{
var cookies = edgeCookie.GetCookies(new Uri(StaticStrings.UrlNCert), false);
var cookieString = new StringBuilder();
foreach (var cookie in cookies)
{
cookieString.Append(cookie.Name + "=" + cookie.Value + "; ");
}
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Cookie", cookieString.ToString());
string searchStr = StaticStrings.CustomerAgreementAPI + customerId;
var response = client.GetStringAsync(searchStr).Result;
List<FrameAgreement> FAList = JsonConvert.DeserializeObject<List<FrameAgreement>>(response);
return FAList;
}
}
public List<Address> GetAddressFromCustomerId(string customerId)
{
using (var edgeCookie = new EdgeCookie())
{
var cookies = edgeCookie.GetCookies(new Uri(StaticStrings.UrlNCert), false);
var cookieString = new StringBuilder();
foreach (var cookie in cookies)
{
cookieString.Append(cookie.Name + "=" + cookie.Value + "; ");
}
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Cookie", cookieString.ToString());
string searchStr = StaticStrings.CustomerAddressAPI + customerId + "/survey-address/all";
var response = client.GetStringAsync(searchStr).Result;
List<Address> AddressList = JsonConvert.DeserializeObject<List<Address>>(response);
return AddressList;
}
}
}
}
WebNav.cs Includes the following code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data;
namespace WeeklySchedule.Contollers
{
public class EdgeCookie : IDisposable
{
private Microsoft.Win32.RegistryKey _edgeKey = null;
public EdgeCookie()
{
_edgeKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(#"Software\Microsoft\Windows\CurrentVersion\AppContainer\Storage\microsoft.microsoftedge_8wekyb3d8bbwe\MicrosoftEdge\Main", false);
}
public List<Cookie> GetCookies(Uri uri, bool v)
{
var cookies = new List<Cookie>();
try
{
if (_edgeKey == null)
{
throw new Exception("Error: _edgeKey is null");
}
var sqliteFile = System.IO.Path.Combine(_edgeKey.GetValue("DataPath").ToString(), "Cookies");
using (var conn = new System.Data.SQLite.SQLiteConnection("Data Source=" + sqliteFile + ";Version=3;"))
{
conn.Open();
using (var cmd = new System.Data.SQLite.SQLiteCommand("select host_key, name, encrypted_value, path, expires_utc, secure, httponly from cookies where host_key like '%" + uri.Host + "%'", conn))
{
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var cookie = new Cookie(
reader.GetString(1),
reader.GetString(2),
reader.GetString(3),
reader.GetString(0));
cookie.Expires = DateTime.FromFileTimeUtc(long.Parse(reader.GetString(4)));
cookie.Secure = reader.GetBoolean(5);
cookie.HttpOnly = reader.GetBoolean(6);
cookies.Add(cookie);
}
}
}
}
}
catch
{
throw new Exception("Error reading cookies from Microsoft Edge");
}
return cookies;
}
public void Dispose()
{
if (_edgeKey != null)
{
_edgeKey.Dispose();
_edgeKey = null;
}
}
}
}

The 'await' operator can only be used within an async > method

I have the following controller:
[Authorize]
public class SetupController : ApiController
{
[HttpPost]
public Task async SetupPartnerPackAsync(SetupInformation info)
{
if (info.SslCertificateGenerate)
{
SetupManager.CreateX509Certificate(info);
}
else
{
SetupManager.LoadX509Certificate(info);
}
info.SslCertificateThumbprint = SetupManager.GetX509CertificateThumbprint(info);
info.AzureAppKeyCredential = SetupManager.GetX509CertificateInformation(info);
await SetupManager.RegisterAzureADApplication(info);
}
}
But I have the following 2 error which seems simple:
Severity Code Description Project File Line Suppression State
Error CS1520 Method must have a return
type InnovationInABoxWebApi H:\InnovationInABoxWebApi\InnovationInABoxWebApi\Controllers\SetupController.cs 24 Active
Severity Code Description Project File Line Suppression State
Error CS4033 The 'await' operator can only be used within an async
method. Consider marking this method with the 'async' modifier and
changing its return type to
'Task'. InnovationInABoxWebApi H:\InnovationInABoxWebApi\InnovationInABoxWebApi\Controllers\SetupController.cs 39 Active
However I am not sure how to fix this, as the operation can take some time to complete, it really needs to be asybnc
and the setupmanager
using CERTENROLLLib;
using Microsoft.Identity.Client;
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.SharePoint.Client;
using Newtonsoft.Json;
using OfficeDevPnP.Core;
using OfficeDevPnP.Core.Entities;
using OfficeDevPnP.Core.Framework.Provisioning.Model;
using OfficeDevPnP.Core.Framework.Provisioning.ObjectHandlers;
using OfficeDevPnP.Core.Framework.Provisioning.Providers.Xml;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Resources;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Xml.Linq;
namespace InnovationInABoxWebApi.Components
{
public static class SetupManager
{
public static String GetX509CertificateThumbprint(SetupInformation info)
{
var certificate = info.AuthenticationCertificate;
return (certificate.Thumbprint.ToUpper());
}
public static String GetX509CertificateInformation(SetupInformation info)
{
// var basePath = String.Format(#"{0}..\..\..\..\Scripts\", AppDomain.CurrentDomain.BaseDirectory);
var certificate = info.AuthenticationCertificate;
//var certificate = new X509Certificate2();
//if (info.SslCertificateGenerate)
//{
// certificate.Import($#"{basePath}{info.SslCertificateCommonName}.cer");
//}
//else
//{
// certificate = new X509Certificate2(info.SslCertificateFile, info.SslCertificatePassword);
//}
var rawCert = certificate.GetRawCertData();
var base64Cert = System.Convert.ToBase64String(rawCert);
var rawCertHash = certificate.GetCertHash();
var base64CertHash = System.Convert.ToBase64String(rawCertHash);
var KeyId = System.Guid.NewGuid().ToString();
var keyCredential =
"{" +
"\"customKeyIdentifier\": \"" + base64CertHash + "\"," +
"\"keyId\": \"" + KeyId + "\"," +
"\"type\": \"AsymmetricX509Cert\"," +
"\"usage\": \"Verify\"," +
"\"key\": \"" + base64Cert + "\"" +
"}";
return (keyCredential);
}
public static void CreateX509Certificate(SetupInformation info)
{
var certificate = CreateSelfSignedCertificate(info.SslCertificateCommonName.ToLower(),
info.SslCertificateStartDate, info.SslCertificateEndDate, info.SslCertificatePassword);
SaveCertificateFiles(info, certificate);
}
public static void LoadX509Certificate(SetupInformation info)
{
var certificate = new X509Certificate2(info.SslCertificateFile, info.SslCertificatePassword);
info.AuthenticationCertificate = certificate;
info.SslCertificateCommonName = certificate.SubjectName.Name;
}
public static void SaveCertificateFiles(SetupInformation info, X509Certificate2 certificate)
{
info.AuthenticationCertificate = certificate;
//var basePath = String.Format(#"{0}..\..\..\..\Scripts\", AppDomain.CurrentDomain.BaseDirectory);
//info.SslCertificateFile = $#"{basePath}{info.SslCertificateCommonName}.pfx";
//var pfx = certificate.Export(X509ContentType.Pfx, info.SslCertificatePassword);
//System.IO.File.WriteAllBytes(info.SslCertificateFile, pfx);
//var cer = certificate.Export(X509ContentType.Cert);
//System.IO.File.WriteAllBytes($#"{basePath}{info.SslCertificateCommonName}.cer", cer);
}
public static X509Certificate2 CreateSelfSignedCertificate(string subjectName, DateTime startDate, DateTime endDate, String password)
{
// Create DistinguishedName for subject and issuer
var name = new CX500DistinguishedName();
name.Encode("CN=" + subjectName, X500NameFlags.XCN_CERT_NAME_STR_NONE);
// Create a new Private Key for the certificate
CX509PrivateKey privateKey = new CX509PrivateKey();
privateKey.ProviderName = "Microsoft RSA SChannel Cryptographic Provider";
privateKey.KeySpec = X509KeySpec.XCN_AT_KEYEXCHANGE;
privateKey.Length = 2048;
privateKey.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)";
privateKey.MachineContext = true;
privateKey.ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_EXPORT_FLAG;
privateKey.Create();
// Define the hashing algorithm
var serverauthoid = new CObjectId();
serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1"); // Server Authentication
var ekuoids = new CObjectIds();
ekuoids.Add(serverauthoid);
var ekuext = new CX509ExtensionEnhancedKeyUsage();
ekuext.InitializeEncode(ekuoids);
// Create the self signing request
var cert = new CX509CertificateRequestCertificate();
cert.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextMachine, privateKey, String.Empty);
cert.Subject = name;
cert.Issuer = cert.Subject;
cert.NotBefore = startDate;
cert.NotAfter = endDate;
cert.X509Extensions.Add((CX509Extension)ekuext);
cert.Encode();
// Enroll the certificate
var enroll = new CX509Enrollment();
enroll.InitializeFromRequest(cert);
string certData = enroll.CreateRequest(EncodingType.XCN_CRYPT_STRING_BASE64HEADER);
enroll.InstallResponse(InstallResponseRestrictionFlags.AllowUntrustedCertificate,
certData, EncodingType.XCN_CRYPT_STRING_BASE64HEADER, String.Empty);
var base64encoded = enroll.CreatePFX(password, PFXExportOptions.PFXExportChainWithRoot);
// Instantiate the target class with the PKCS#12 data
return new X509Certificate2(
System.Convert.FromBase64String(base64encoded), password,
System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.Exportable);
}
public async static Task RegisterAzureADApplication(SetupInformation info)
{
// Fix the App URL
if (!info.AzureWebAppUrl.EndsWith("/"))
{
info.AzureWebAppUrl = info.AzureWebAppUrl + "/";
}
// Load the App Manifest template
//Stream stream = typeof(SetupManager)
// .Assembly
// .GetManifestResourceStream("OfficeDevPnP.PartnerPack.Setup.Resources.azure-ad-app-manifest.json");
using (StreamReader sr = new StreamReader("Resources\azure-ad-app-manifest.json"))
{
// Get the JSON manifest
var jsonApplication = sr.ReadToEnd();
var application = JsonConvert.DeserializeObject<AzureAdApplication>(jsonApplication);
var keyCredential = JsonConvert.DeserializeObject<KeyCredential>(info.AzureAppKeyCredential);
application.displayName = info.ApplicationName;
application.homepage = info.AzureWebAppUrl;
application.identifierUris = new List<String>();
application.identifierUris.Add(info.ApplicationUniqueUri);
application.keyCredentials = new List<KeyCredential>();
application.keyCredentials.Add(keyCredential);
application.replyUrls = new List<String>();
application.replyUrls.Add(info.AzureWebAppUrl);
// Generate the Application Shared Secret
var startDate = DateTime.Now;
Byte[] bytes = new Byte[32];
using (var rand = System.Security.Cryptography.RandomNumberGenerator.Create())
{
rand.GetBytes(bytes);
}
info.AzureAppSharedSecret = System.Convert.ToBase64String(bytes);
application.passwordCredentials = new List<object>();
application.passwordCredentials.Add(new AzureAdApplicationPasswordCredential
{
CustomKeyIdentifier = null,
StartDate = startDate.ToString("o"),
EndDate = startDate.AddYears(2).ToString("o"),
KeyId = Guid.NewGuid().ToString(),
Value = info.AzureAppSharedSecret,
});
// Get an Access Token to create the application via Microsoft Graph
var office365AzureADAccessToken = await AzureManagementUtility.GetAccessTokenSilentAsync(
AzureManagementUtility.MicrosoftGraphResourceId,
ConfigurationManager.AppSettings["O365:ClientId"]);
var azureAdApplicationCreated = false;
// Create the Azure AD Application
try
{
await CreateAzureADApplication(info, application, office365AzureADAccessToken);
azureAdApplicationCreated = true;
}
catch (ApplicationException ex)
{
var graphError = JsonConvert.DeserializeObject<GraphError>(((HttpException)ex.InnerException).Message);
if (graphError != null && graphError.error.code == "Request_BadRequest" &&
graphError.error.message.Contains("identifierUris already exists"))
{
// We need to remove the existing application
// Thus, retrieve it
String jsonApplications = await HttpHelper.MakeGetRequestForStringAsync(
String.Format("{0}applications?$filter=identifierUris/any(c:c+eq+'{1}')",
AzureManagementUtility.MicrosoftGraphBetaBaseUri,
HttpUtility.UrlEncode(info.ApplicationUniqueUri)),
office365AzureADAccessToken);
var applications = JsonConvert.DeserializeObject<AzureAdApplications>(jsonApplications);
var applicationToUpdate = applications.Applications.FirstOrDefault();
if (applicationToUpdate != null)
{
// Remove it
await HttpHelper.MakeDeleteRequestAsync(
String.Format("{0}applications/{1}",
AzureManagementUtility.MicrosoftGraphBetaBaseUri,
applicationToUpdate.Id),
office365AzureADAccessToken);
// And add it again
await CreateAzureADApplication(info, application, office365AzureADAccessToken);
azureAdApplicationCreated = true;
}
}
}
if (azureAdApplicationCreated)
{
// TODO: We should upload the logo
// property mainLogo: stream of the application via PATCH
}
}
}
public static async Task CreateAzureADApplication(SetupInformation info, AzureAdApplication application, string office365AzureADAccessToken)
{
String jsonResponse = await HttpHelper.MakePostRequestForStringAsync(
String.Format("{0}applications",
AzureManagementUtility.MicrosoftGraphBetaBaseUri),
application,
"application/json", office365AzureADAccessToken);
var azureAdApplication = JsonConvert.DeserializeObject<AzureAdApplication>(jsonResponse);
info.AzureAppClientId = azureAdApplication.AppId.HasValue ? azureAdApplication.AppId.Value : Guid.Empty;
}
}
}
You are defining the method with async word after the return type Task, async must be before Task.
public async Task SetupPartnerPackAsync(SetupInformation info)
{
.
.
.

Calling web api from another web api

I am new to json and web api.
I created a service called AdminService which has a get method. Kindly see below the get method:
[Route("{iUserId:long}/{iSegmentId:long}/GetUserSegmentItemBySegmentIdAndUserId")]
public IEnumerable<spADGetUserSegmentItemBySegmentIdAndUserId> GetUserSegmentItemBySegmentIdAndUserId(long iUserId, long iSegmentId)
{
using (ADMINEntities context = new ADMINEntities())
{
var usibsu = context.spADGetUserSegmentItemBySegmentIdAndUserId(iUserId, iSegmentId);
if (usibsu != null) return usibsu.ToList();
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
}
The service is working correctly.
Now, I have another service called TestService in which i want to call the get method i created in the adminservice.
Below is my code:
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;
using Newtonsoft.Json;
using NPAService.Models;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
namespace NPAService.Controllers
{
public class HomeController : Controller
{
private string ServiceURLBase = ConfigurationManager.AppSettings["AdminUrl"];
public ActionResult Index()
{
return View();
}
private void MoveImageFiles()
{
DirectoryInfo dirInfo = new DirectoryInfo(Server.MapPath("~/Reports/"));
List<String> FileNames = new List<string>();
for (int i = 0; i < dirInfo.GetFiles().Length; i++)
{
FileNames.Add(dirInfo.GetFiles()[i].FullName);
}
for (int i = 0; i < FileNames.Count; i++)
{
FileInfo fileInfo = new FileInfo(FileNames[i]);
//Delete file if it is older than five minutes
if (DateTime.Now.Subtract(fileInfo.CreationTime).TotalMinutes > 1.0)
{
System.IO.File.Delete(fileInfo.FullName);
//if the file exists at the destination folder, delete it as well
if (System.IO.File.Exists(Server.MapPath("~/Home/images/") + fileInfo.Name))
{
System.IO.File.Delete(Server.MapPath("~/Home/images/") + fileInfo.Name);
}
}
else //Copy file to where it can get displayed on the report if it is less than 5 minute old
{
if (!System.IO.File.Exists(Server.MapPath("~/Home/images/") + fileInfo.Name))
{
System.IO.File.Copy(fileInfo.FullName, Server.MapPath("~/Home/images/") + fileInfo.Name);
}
}
}
}
public string GetUserDataSegment(long iUserId, long iSegmentId)
{
string ListString = string.Empty;
var userdata = new UserData();
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(ServiceURLBase);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = client.GetAsync(iUserId + "/" + iSegmentId + "/GetUserSegmentItemBySegmentIdAndUserId").Result;
if (response.IsSuccessStatusCode)
{
var data = response.Content.ReadAsStringAsync();
var product = JsonConvert.DeserializeObject<UserData>(data);
//foreach (var str in data)
//{
//ListString = str.MyList;
//if (iSegmentId == 1) //'Depot'
//{
// ListString = ("iRegionId IN (" + str.MyList + ")");
//}
//else if (iSegmentId == 2) //'BDC'
//{
//}
//else if (iSegmentId == 3) //'LPGMC'
//{
//}
//else if (iSegmentId == 4) //'Region'
//{
// ListString = ListString + (" and iRegionId IN (" + str.MyList + ")");
//}
//else if (iSegmentId == 5) //'OMC'
//{
// ListString = ListString + (" and iOMCId IN (" + str.MyList + ")");
// ListString = "";
//}
//else if (iSegmentId == 6) //'Zone'
//{
//}
//}
}
}
return ListString;
}
[System.Web.Mvc.HttpGet]
public ActionResult OutletReportListing(long lngCompanyId, string strszITSfromPersol,
string strsQuery1, string strsQuery2, string strsQuery3, string strsQuery4,
string strPicHeight, string strPicWeight, string strCompany, long iUserId, string type)
{
string Username = Convert.ToString(ConfigurationManager.AppSettings["username"]);
string Password = Convert.ToString(ConfigurationManager.AppSettings["password"]);
string Servername = Convert.ToString(ConfigurationManager.AppSettings["DSN"]);
string Databasename = Convert.ToString(ConfigurationManager.AppSettings["databasename"]);
//GetUserDataSegment(iUserId, 5).Wait();
//var myObjList = JSON.Deserialize<List<GetUserDataSegment>>(iUserId, 5);
//var objResponse1 =
// JsonConvert.DeserializeObject<List<UserData>>(iUserId, 5);
string strOMC = GetUserDataSegment(iUserId,5);
string strRegion = GetUserDataSegment(iUserId, 4);
ReportDocument reportdocument = new ReportDocument();
reportdocument.Load(Server.MapPath("~/Reports/rptNPAOutletListing.rpt"));
reportdocument.SetDatabaseLogon(Username, Password, Servername, Databasename);
reportdocument.SetParameterValue("#iCompanyId", lngCompanyId);
reportdocument.SetParameterValue("#szITSfromPersol", strszITSfromPersol);
reportdocument.SetParameterValue("#szQuery1", strsQuery1);
reportdocument.SetParameterValue("#szQuery2", strsQuery2);
reportdocument.SetParameterValue("#szQuery3", strOMC); //strOMC
reportdocument.SetParameterValue("#szQuery4", strRegion); //strRegion
reportdocument.SetParameterValue("#szPicHeight", strPicHeight);
reportdocument.SetParameterValue("#szPicWeight", strPicWeight);
reportdocument.SetParameterValue("#szCompany", strCompany);
ExportFormatType formtType = ExportFormatType.HTML40;
string ExportName = "NPAReport.html";
string ExportMimeType = "text/html";
if (type.Trim().ToLower().Equals("view"))
{
formtType = ExportFormatType.HTML40;
ExportName = "NPAReport.html";
ExportMimeType = "text/html";
}
else if (type.Trim().ToLower().Equals("pdf"))
{
formtType = ExportFormatType.PortableDocFormat;
ExportName = "NPAReport.pdf";
ExportMimeType = "application/pdf";
}
else if (type.Trim().ToLower().Equals("doc"))
{
formtType = ExportFormatType.WordForWindows;
ExportName = "NPAReport.doc";
ExportMimeType = "application/msword";
}
else if (type.Trim().ToLower().Equals("rtf"))
{
formtType = ExportFormatType.RichText;
ExportName = "NPAReport.rtf";
ExportMimeType = "application/rtf";
}
else if (type.Trim().ToLower().Equals("xls"))
{
formtType = ExportFormatType.Excel;
ExportName = "NPAReport.xls";
ExportMimeType = "application/vnd.ms-excel";
}
reportdocument.ExportToDisk(formtType, Server.MapPath("~/Reports/" + ExportName));
MoveImageFiles();
return File(Server.MapPath("~/Reports/" + ExportName), ExportMimeType);
}
}
}
As you can see, i want to generate a report file in my api project. But the first error i am getting is:
cannot convert from 'System.Threading.Tasks.Task' to 'string'
I have done a lot of research but none does not seem to work.
Any help or explanation would be appreciated. Thank you.
response.Content.ReadAsStringAsync();
Async calls return Task<T> . When you want to read the string you call .Result property and you get the string. There is also a way to make async call synchronous. When you call an async method, your method gets out of execution and your method's caller continues execution. When async call completes, then your method continues its execution right after async method. Also since you call async method from GetUserDataSegment method, it also needs to be labeled as async.

ProcessEvent not called in TFS plugin

Recently i have decided to create a plugin for the TFS for tracking work item changes based on ISubscriber interface.
So the workflow would be the following:
1) Work item state changes
2) Plugin catches the WorkItemChangedEvent
3) Send an email to the person specified in the Requester
As the base for my project, i used the following project from CodePlex - The Mail Alert
After i adopted it to my needs and saved compiled binaries in %TFS-DIR%\Microsoft Team Foundation Server 14.0\Application Tier\Web Services\bin\Plugins the TFS restarted the tier and... that's it. On work item change the ProcessEvent method is not called, but it should be.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Common;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.Framework.Server;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Server;
using System.Diagnostics;
using System.Xml.Linq;
using System.Xml;
using System.DirectoryServices;
using System.Net.Mail;
using System.Xml.Xsl;
using System.Configuration;
using System.Reflection;
namespace MailAlert
{
public class WorkItemChangedEventHandler : ISubscriber
{
static string serverPath = "";
static string ExternalURL = "";
static string MailAddressFrom = "";
static string SMTPHost = "";
static string Password = "";
static int Port = 25;
static int index = 0;
static string projectCollectionFolder;
static Uri projectCollectionUri;
static WorkItemStore wiStore;
static WorkItem wItem;
static WorkItemChangedEvent workItemChangedEvent;
static string teamProjectPath = "";
static VersionControlServer versionControlServer;
static TfsTeamProjectCollection projectCollection;
static Dictionary<IdentityDescriptor, TeamFoundationIdentity> m_identities = new Dictionary<IdentityDescriptor, TeamFoundationIdentity>(IdentityDescriptorComparer.Instance);
public Type[] SubscribedTypes()
{
return new Type[1] { typeof(WorkItemChangedEvent) };
}
public WorkItemChangedEventHandler()
{
TeamFoundationApplicationCore.Log("WorkItemChangedEvent Started", index++, EventLogEntryType.Information);
}
public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType,
object notificationEventArgs, out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties)
{
TeamFoundationApplicationCore.Log("WorkItemChangedEventHandler: ProcessEvent entered", index++, EventLogEntryType.Information);
statusCode = 0;
properties = null;
statusMessage = String.Empty;
GetTfsServerName();
projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(TfsTeamProjectCollection.GetFullyQualifiedUriForName(serverPath));
try
{
if (notificationType == NotificationType.Notification && notificationEventArgs is WorkItemChangedEvent)
{
workItemChangedEvent = notificationEventArgs as WorkItemChangedEvent;
TeamFoundationApplicationCore.Log("WorkItemChangedEventHandler: WorkItem " + workItemChangedEvent.WorkItemTitle + " was modified", index++, EventLogEntryType.Information);
TeamFoundationApplicationCore.Log("WorkItemChangedEventHandler: serverPath - " + serverPath, index++, EventLogEntryType.Information);
projectCollectionFolder = requestContext.ServiceHost.VirtualDirectory.ToString();
projectCollectionUri = new Uri(serverPath + projectCollectionFolder);
projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(projectCollectionUri);
wiStore = projectCollection.GetService<WorkItemStore>();
versionControlServer = projectCollection.GetService<VersionControlServer>();
TeamFoundationApplicationCore.Log("WorkItemChangedEventHandler: Before process workitem", index++, EventLogEntryType.Information);
ProcessWorkItem();
TeamFoundationApplicationCore.Log("WorkItemChangedEventHandler: After process workitem", index++, EventLogEntryType.Information);
}
}
catch (Exception ex)
{
TeamFoundationApplicationCore.Log("WorkItemChangedEventHandler: FUCKING EXCEPTION! =>\n" + ex.Message, index++, EventLogEntryType.Error);
}
return EventNotificationStatus.ActionPermitted;
}
private static void GetTfsServerName()
{
try
{
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
XmlDocument XmlDoc = new XmlDocument();
XmlDoc.Load(assemblyFolder + #"\Settings.xml");
// Declare the xpath for finding objects inside the XML file
XmlNodeList XmlDocNodes = XmlDoc.SelectNodes("/configuration/tfssettings");
XmlNodeList XmlDocExt = XmlDoc.SelectNodes("/configuration/Externaltfssettings");
// Define a new List, to store the objects we pull out of the XML
serverPath = XmlDocNodes[0].InnerText;
ExternalURL = XmlDocExt[0].InnerText;
XmlNodeList XmlDocNodes2 = XmlDoc.SelectNodes("/configuration/appSettings");
foreach (XmlNode mailNode in XmlDocNodes2)
{
foreach (XmlNode varElement in mailNode.ChildNodes)
{
switch (varElement.Attributes["key"].Value)
{
case "MailAddressFrom":
MailAddressFrom = varElement.Attributes["value"].Value;
break;
case "SMTPHost":
SMTPHost = varElement.Attributes["value"].Value;
break;
case "Password":
Password = varElement.Attributes["value"].Value;
break;
case "Port":
Port = Convert.ToInt32(varElement.Attributes["value"].Value);
break;
}
}
}
}
catch (Exception ex)
{
EventLog.WriteEntry("WorkItemChangedEventHandler", ex.Message);
}
}
public string Name
{
get { return "WorkItemChangedEventHandler"; }
}
public SubscriberPriority Priority
{
get { return SubscriberPriority.High; }
}
private static void ProcessWorkItem()
{
var teamProjects = versionControlServer.GetAllTeamProjects(false);
for (int i = 0; i < teamProjects.Length; i++)
{
string teamProjectName = teamProjects[i].Name;
var teamProject = teamProjects[i];
Project teamProjectWI = wiStore.Projects[i];
teamProjectPath = projectCollectionUri + teamProject.Name;
if (workItemChangedEvent.PortfolioProject == teamProjectName)
{
//get the workitem by ID ( CoreFields.IntegerFields[0] == ID ?!)
//check if any of String changed fields
foreach(StringField sf in workItemChangedEvent.ChangedFields.StringFields)
{
//is the State field
if (sf.Name.Equals("State"))
{
//then notify Reuqester
wItem = wiStore.GetWorkItem(workItemChangedEvent.CoreFields.IntegerFields[0].NewValue);
string CollGuid = projectCollection.InstanceId.ToString();
string Requester = wItem.Fields["Requester"].Value.ToString();
string WorkItemId = wItem.Id.ToString();
string mail = GetEmailAddress(Requester);
SendMail(CollGuid, WorkItemId, mail);
}
}
}
}
}
private static string GetEmailAddress(string userDisplayName)
{
DirectorySearcher ds = new DirectorySearcher();
ds.PropertiesToLoad.Add("mail");
ds.Filter = String.Format("(&(displayName={0})(objectCategory=person)((objectClass=user)))", userDisplayName);
SearchResultCollection results = ds.FindAll();
if (results.Count == 0)
{
return string.Empty;
}
ResultPropertyValueCollection values = results[0].Properties["mail"];
if (values.Count == 0)
{
return string.Empty;
}
return values[0].ToString();
}
private static void SendMail(string collID,string workItemId,string tomailAddrees)
{
MailMessage objeto_mail = new MailMessage();
SmtpClient client = new SmtpClient();
client.Port = Port;
client.Host = SMTPHost;
client.Timeout = 200000;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = true;
client.EnableSsl = true;
client.Credentials = new System.Net.NetworkCredential(MailAddressFrom, Password);
objeto_mail.From = new MailAddress(MailAddressFrom);
objeto_mail.To.Add(new MailAddress(tomailAddrees));
//objeto_mail.CC.Add(new MailAddress("nagarajb#hotmail.com"));
objeto_mail.Subject = "Work Item Changed:"+workItemId;
string mailbody = serverPath+"/tfs/web/wi.aspx?pcguid=" + collID + "&id=" + workItemId;
string mailbody2 = "";
if (ExternalURL.Length > 0)
{
mailbody2 = ExternalURL + "/tfs/web/wi.aspx?pcguid=" + collID + "&id=" + workItemId;
}
string tables = "<table border=1><tr><td>Work Item ID</td><td>" + wItem.Id.ToString() + "</td></tr><tr><td>Title</td><td>" + wItem.Title + "</td></tr><tr><td>State</td><td>" + wItem.State + "</td></tr><tr><td>Assigned To</td><td>" + wItem.Fields["Assigned to"].Value.ToString() + "</td></tr><tr><td>Internal URL</td><td>" + mailbody + "</td></tr><tr><td>External URL</td><td>" + mailbody2 + "</td></tr></table>";
objeto_mail.IsBodyHtml = true;
objeto_mail.Body = "<i>Hi " + wItem.Fields["Requester"].Value.ToString() + ","+"</i></br></br></br>" + tables + " </br></br> Best regards; </br></br>Configuration Management Team</br></br></br>";
client.Send(objeto_mail);
EventLog.WriteEntry("WorkItemChangedEventHandler", "Email Sent");
}
}
}
No errors or exceptions are thrown in the Event Log either. Tracing TFS (trace=true property in web.config) also was of no help.
Maybe someone could help or shed light on this mysterious case?
UPDATE:
Thanks for a reply Giulio Vian!
Here how it goes:
1) I haven't seen the dependencies broken, plus the constructor WorkItemChangedEventHandler is successfully called. That is seen in the Windows Event Log - WorkItemChangedEvent Started message is written.
2) I am not sure how to register the event handler.... i'll look that up
3) I am not sure how this works. I thought just copy-pasting dlls in the appropriate folder will do the trick, and there is no need for an account for the plugin. Mind giving a bit more info on this?
4) yes. Web.config in the main Web config in Application Tier\Web Services
5) Yes. Using an account with Administer rights. if i set a break point in the constructor, it is reached. Any other place in the code is not reached.
Many things can be wrong.
If any dependency is broken, you should see an error in the Event log
If you do not register the "WorkItemChangedEventHandler" event source, no message is written
Can the user account running the plugin access TFS?
How did you enabled the tracing (you pasted a bunch of code, but no configuration)?
Have you attached the debugger to the TFS process and set a breakpoint (do not this on a production TFS)?
We have collected similar suggestions in the documentation for our plugin at
https://github.com/tfsaggregator/tfsaggregator/wiki.

WCF - create UserNameToken with timestamp and password digest for oasis-200401-wss-username-token-profile-1.0

The objective is, by using WCF, connect to a Web service that requires UserNameToken ws-security as specified by the standard "oasis-200401-wss-soap-message-security-1.0".
Full specification can be find here http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf
There are few examples of how to create the token and none worked for me.
When i posted this i had already found the answer but since it was not easy, i let here the solution i found and hope it can be improved. So i will just jump to the answer.
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens;
using System.Security.Cryptography;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Channels;
using System.Text;
using System.Threading.Tasks;
namespace WSClient
{
//Create this custom credentials class to implement UserNameToken autentication
public class CustomCredentials : ClientCredentials
{
public CustomCredentials()
{ }
protected CustomCredentials(CustomCredentials cc)
: base(cc)
{ }
public override System.IdentityModel.Selectors.SecurityTokenManager CreateSecurityTokenManager()
{
return new CustomSecurityTokenManager(this);
}
protected override ClientCredentials CloneCore()
{
return new CustomCredentials(this);
}
}
public class CustomSecurityTokenManager : ClientCredentialsSecurityTokenManager
{
public CustomSecurityTokenManager(CustomCredentials cred)
: base(cred)
{ }
public override System.IdentityModel.Selectors.SecurityTokenSerializer CreateSecurityTokenSerializer(System.IdentityModel.Selectors.SecurityTokenVersion version)
{
return new CustomTokenSerializer(System.ServiceModel.Security.SecurityVersion.WSSecurity10);
}
}
public class CustomTokenSerializer : WSSecurityTokenSerializer
{
public CustomTokenSerializer(SecurityVersion sv)
: base(sv)
{ }
protected override void WriteTokenCore(System.Xml.XmlWriter writer,
System.IdentityModel.Tokens.SecurityToken token)
{
UserNameSecurityToken userToken = token as UserNameSecurityToken;
string tokennamespace = "o";
DateTime created = DateTime.UtcNow;
string createdStr = created.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
string phrase = Guid.NewGuid().ToString();
var nonce = Convert.ToBase64String(Encoding.UTF8.GetBytes(phrase));
SHA1CryptoServiceProvider sha1Hasher = new SHA1CryptoServiceProvider();
//Password_Digest = Base64 ( SHA-1 ( nonce + created + password ) )
string Password_Digest = Convert.ToBase64String(sha1Hasher.ComputeHash(Encoding.UTF8.GetBytes(phrase + createdStr + userToken.Password))); // pxLqPLCXU1EiUS+NnpRuCw==
var stringToWrite = string.Format(
"<{0}:UsernameToken u:Id=\"" + token.Id +
"\" xmlns:u=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">" +
"<{0}:Username>" + userToken.UserName + "</{0}:Username>" +
"<{0}:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest\">" +
Password_Digest + "</{0}:Password>" +
"<{0}:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">" +
nonce + "</{0}:Nonce>" +
"<u:Created>" + createdStr + "</u:Created></{0}:UsernameToken>", tokennamespace);
writer.WriteRaw(stringToWrite);
}
}
class Program
{
static void Main(string[] args)
{
try
{
//for invalid ssl server certificate
System.Net.ServicePointManager.ServerCertificateValidationCallback +=
(se, cert, chain, sslerror) =>
{
return true;
};
CustomBinding binding = new CustomBinding();
var security = TransportSecurityBindingElement.CreateUserNameOverTransportBindingElement();
security.IncludeTimestamp = true;
security.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256;
security.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10;
security.EnableUnsecuredResponse = true;
var encoding = new TextMessageEncodingBindingElement();
encoding.MessageVersion = MessageVersion.Soap11;
var transport = new HttpsTransportBindingElement();
transport.MaxReceivedMessageSize = 2000000;
binding.Elements.Add(security);
binding.Elements.Add(encoding);
binding.Elements.Add(transport);
WSClient.Proxy.TargetWS client = new Proxy.TargetWS(binding,
new EndpointAddress(Properties.Settings.Default.Url));
//change credential for the custom credentials instance
client.ChannelFactory.Endpoint.Behaviors.Remove<System.ServiceModel.Description.ClientCredentials>();
client.ChannelFactory.Endpoint.Behaviors.Add(new CustomCredentials());
client.ClientCredentials.UserName.UserName = Properties.Settings.Default.username;
client.ClientCredentials.UserName.Password = Properties.Settings.Default.password;
Proxy.Message message = new WSClient.Proxy.Message();
message.id = "whatever";
client.foo(message);
System.Console.Write("Success");
}
catch (Exception ex)
{
System.Console.Write(ex.Message);
}
}
}
}
a bit extensive!
Essentially, it is need to serialize the token according to Oasys specifications. To do this it is need to derivate ClientCredentials, ClientCredentialsSecurityTokenManager and WSSecurityTokenSerializer in the way presented.
About the binding, not sure if works for all or if variations are allowed by the specification.

Categories