I'm trying to get the following to work on my machine but I get an error (Cannot create an instance of the abstract class or interface 'System.ServiceModel.Channels.MessageHeader')
using System;
using System.IO;
using System.Reflection;
namespace com.companyname.business
{
/// <summary>
/// Summary description for SessionCreateRQClient.
/// </summary>
class SessionCreateRQClient
{
/// <summary>
/// The main entry point.
/// </summary>
[STAThread]
static void Main(string[] args)
{
try
{
// Set user information, including security credentials and the IPCC.
string username = "user";
string password = "password";
string ipcc = "IPCC";
string domain = "DEFAULT";
string temp = Environment.GetEnvironmentVariable("tmp"); // Get temp directory
string PropsFileName = temp + "/session.properties"; // Define dir and file name
DateTime dt = DateTime.UtcNow;
string tstamp = dt.ToString("s") + "Z";
//Create the message header and provide the conversation ID.
MessageHeader msgHeader = new MessageHeader();
msgHeader.ConversationId = "TestSession"; // Set the ConversationId
From from = new From();
PartyId fromPartyId = new PartyId();
PartyId[] fromPartyIdArr = new PartyId[1];
fromPartyId.Value = "WebServiceClient";
fromPartyIdArr[0] = fromPartyId;
from.PartyId = fromPartyIdArr;
msgHeader.From = from;
To to = new To();
PartyId toPartyId = new PartyId();
PartyId[] toPartyIdArr = new PartyId[1];
toPartyId.Value = "WebServiceSupplier";
toPartyIdArr[0] = toPartyId;
to.PartyId = toPartyIdArr;
msgHeader.To = to;
//Add the value for eb:CPAId, which is the IPCC.
//Add the value for the action code of this Web service, SessionCreateRQ.
msgHeader.CPAId = ipcc;
msgHeader.Action = "SessionCreateRQ";
Service service = new Service();
service.Value = "SessionCreate";
msgHeader.Service = service;
MessageData msgData = new MessageData();
msgData.MessageId = "mid:20001209-133003-2333#clientofsabre.com1";
msgData.Timestamp = tstamp;
msgHeader.MessageData = msgData;
Security security = new Security();
SecurityUsernameToken securityUserToken = new SecurityUsernameToken();
securityUserToken.Username = username;
securityUserToken.Password = password;
securityUserToken.Organization = ipcc;
securityUserToken.Domain = domain;
security.UsernameToken = securityUserToken;
SessionCreateRQ req = new SessionCreateRQ();
SessionCreateRQPOS pos = new SessionCreateRQPOS();
SessionCreateRQPOSSource source = new SessionCreateRQPOSSource();
source.PseudoCityCode = ipcc;
pos.Source = source;
req.POS = pos;
SessionCreateRQService serviceObj = new SessionCreateRQService();
serviceObj.MessageHeaderValue = msgHeader;
serviceObj.SecurityValue = security;
SessionCreateRS resp = serviceObj.SessionCreateRQ(req); // Send the request
if (resp.Errors != null && resp.Errors.Error != null)
{
Console.WriteLine("Error : " + resp.Errors.Error.ErrorInfo.Message);
}
else
{
msgHeader = serviceObj.MessageHeaderValue;
security = serviceObj.SecurityValue;
Console.WriteLine("**********************************************");
Console.WriteLine("Response of SessionCreateRQ service");
Console.WriteLine("BinarySecurityToken returned : " + security.BinarySecurityToken);
Console.WriteLine("**********************************************");
string ConvIdLine = "convid="+msgHeader.ConversationId; // ConversationId to a string
string TokenLine = "securitytoken="+security.BinarySecurityToken; // BinarySecurityToken to a string
string ipccLine = "ipcc="+ipcc; // IPCC to a string
File.Delete(PropsFileName); // Clean up
TextWriter tw = new StreamWriter(PropsFileName); // Create & open the file
tw.WriteLine(DateTime.Now); // Write the date for reference
tw.WriteLine(TokenLine); // Write the BinarySecurityToken
tw.WriteLine(ConvIdLine); // Write the ConversationId
tw.WriteLine(ipccLine); // Write the IPCC
tw.Close();
//Console.Read();
}
}
catch(Exception e)
{
Console.WriteLine("Exception Message : " + e.Message );
Console.WriteLine("Exception Stack Trace : " + e.StackTrace);
Console.Read();
}
}
}
}
I have added the reference System.ServiceModel and the lines:
using System.ServiceModel;
using System.ServiceModel.Channels;
but I continue to get that error when trying to compile --
Cannot create an instance of the abstract class or interface 'System.ServiceModel.Channels.MessageHeader'
I am using Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
Professional Edition
Is there another reference I have to add? Or a dll to move over?
I wonder was the code above written for Framework 2.0 only?
Thanks for your help.
The error message is correct, you cannot create an instance of that class, it is declared abstract.
http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.messageheader.aspx
See if the static method MessageHeader.CreateHeader will work for you. Note there is several overloads, so pick the best one for you.
Related
I need to get (not download) the content from 10.000~ manifest files within a project in Azure DevOps, but I don't manage to achieve this. I have found several ways to retrieve the content from one file at a time, but in this context, it is neither an efficient nor sustainable solution. I have managed to retrieve all files of a particular file type by checking if the file path ends with the name of the file, then using the TfvcHttpClientBase.GetItemsBatch method. However, this method does not return the item's content.
Program.cs
using Microsoft.TeamFoundation.SourceControl.WebApi;
AzureRest azureRest = new AzureRest();
var tfvcItems = azureRest.GetTfvcItems();
List<TfvcItemDescriptor> itemDescriptorsList = new List<TfvcItemDescriptor>();
foreach(var item in tfvcItems)
{
//Example manifest file .NET
if (item.Path.EndsWith("packages.config"))
{
var itemDescriptor = new TfvcItemDescriptor()
{
Path = item.Path,
RecursionLevel = VersionControlRecursionType.None,
Version = "",
VersionOption = TfvcVersionOption.None,
VersionType = TfvcVersionType.Latest
};
itemDescriptorsList.Add(itemDescriptor);
}
}
TfvcItemDescriptor[] itemDescriptorsArray = itemDescriptorsList.ToArray();
var itemBatch = azureRest.GetTfvcItemsBatch(itemDescriptorsArray);
foreach(var itemList in itemBatch)
{
foreach(var itemListList in itemList)
{
Console.WriteLine("Content: " + itemListList.Content); //empty/null
Console.WriteLine("ContentMetadata: " + itemListList.ContentMetadata); //not empty/null
}
}
AzureRest.cs
using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.WebApi;
public class AzureRest
{
const string ORG_URL = "https://org/url/url";
const string PROJECT = "Project";
const string PAT = "PersonalAccessToken";
private string GetTokenConfig()
{
return PAT;
}
private string GetProjectNameConfig()
{
return PROJECT;
}
private VssConnection Authenticate()
{
string token = GetTokenConfig();
string projectName = GetProjectNameConfig();
var credentials = new VssBasicCredential(string.Empty, token);
var connection = new VssConnection(new Uri(ORG_URL), credentials);
return connection;
}
public List<TfvcItem> GetTfvcItems()
{
var connection = Authenticate();
using (TfvcHttpClient tfvcClient = connection.GetClient<TfvcHttpClient>())
{
var tfvcItems = tfvcClient.GetItemsAsync(scopePath: "/Path", recursionLevel: VersionControlRecursionType.Full, true).Result;
return tfvcItems;
}
}
public List<List<TfvcItem>> GetTfvcItemsBatch(TfvcItemDescriptor[] itemDescriptors)
{
TfvcItemRequestData requestData = new TfvcItemRequestData()
{
IncludeContentMetadata = true,
IncludeLinks = true,
ItemDescriptors = itemDescriptors
};
var connection = Authenticate();
using (TfvcHttpClient tfvcClient = connection.GetClient<TfvcHttpClient>())
{
var tfvcItems = tfvcClient.GetItemsBatchAsync(requestData).Result;
return tfvcItems;
}
}
}
}
For reference:
I have tested the codes you shared and when debugging at "itemDescriptorsList" and have found that there is no content specified in it, so that's why you cannot get the txt content.
You should first check and add the content property into the "itemDescriptorsList".
I have an application that is written in C# so that it can be a stand-alone .exe with parameters passed in via cmd at runtime. I am trying to update a file in google drive without changing the fileid so that any links using that id will not be broken. The following code works until it gets to the third section using Google.Apis.Drive.v3.Data.File updateFile in which the file is always 'null'. The request.ResponseBody has the correct fileId, the correct path and all but always comes up null.
How can I get this to update a file?
Is there some code update/change that no longer works?
Any help would be appreciated-
Section 1- This is the start of the code that calls the next two sections:
// System Library Requirements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Security;
// Microsoft Library Requirements
using Microsoft.Win32;
// Google API Library Requirements
using Google.Apis.Gmail.v1;
using Google.Apis.Gmail.v1.Data;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v3;
using GoogleV2 = Google.Apis.Drive.v2;
using Google.Apis.Drive.v3.Data;
using GoogleV2data = Google.Apis.Drive.v2.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using Google.Apis.Requests;
using Google.Apis.Auth.OAuth2.Responses;
using Google.Api.Gax;
using Google.Cloud.Channel.V1;
// JSON reading/serializing/De-serializing Library Requirements
using Newtonsoft.Json;
// Mime-Type Library Requirements
using MimeKit;
using Google.Apis.Upload;
// CyberArk Library Requirements
using CyberArk.AIM.NetPasswordSDK;
using CyberArk.AIM.NetPasswordSDK.Exceptions;
static class Globals
{
//cyberark values will change based on the domain and the app and the safe
public static string google_client_secret;
public static string cyberark_client_id = "...xxxx.....apps.googleusercontent.com";
public static string cyberark_object = "...xxx...";
public static string cyberark_app_id = "...xxx...";
public static string cyberark_safe = "...xxx...";
//google app values will change based on the domain and gcp project information e.g. np vs prod
public static string google_app_name = "my_google_app_name";
public static string google_client_id = "my_google_client_id";
public static string google_data_store = "my_google_data_store";
}
class Program
{
static void Main(string[] args)
{
Globals.google_client_secret = NetPasswordSDK.CyberArkProgram.GetMyPassword(NetPasswordSDK.MyCredentials.MY_APP_ID, NetPasswordSDK.MyCredentials.MY_SAFE, NetPasswordSDK.MyCredentials.MY_OBJECT, NetPasswordSDK.MyCredentials.MY_SECURE_STRING);
var paramFolderID = "";
var paramDriveFromFolderName = "";
var paramUserID = "";
var paramTeamID = "";
var paramFileName = "";
var paramFilePath = "";
var paramLocalFolderPath = "";
if (args == null || args.Length == 0)
{
Console.WriteLine("No Arguments passed");
}
else
{
paramFolderID = args[0];
paramDriveFromFolderName = args[1];
paramUserID = args[2];
paramTeamID = args[3];
paramFileName = args[4];
paramFilePath = args[5];
paramLocalFolderPath = args[6];
Console.WriteLine("FolderID " + args[0]);
Console.WriteLine("DriveFromFolderName " + args[1]);
Console.WriteLine("UserID " + args[2]);
Console.WriteLine("TeamID " + args[3]);
Console.WriteLine("FileName " + args[4]);
Console.WriteLine("FilePath " + args[5]);
Console.WriteLine("LocalFolderPath " + args[6]);
}
string googleUpdateText = "";
string googleUpdateFilePath = "";
string googleUpdateLocalFolderPath = "";
string googleUpdateFileName = "";
string googleUpdateParentFolder = "";
string googleUpdateTeamDriveID = "";
string googleUpdateParentFolderID = "";
var proxy = WebRequest.DefaultWebProxy;
proxy.Credentials = CredentialCache.DefaultCredentials;
var httpClientHandler = new HttpClientHandler()
{
Proxy = proxy
};
{
{
//googleUpdateParentFolderID = paramFolderID;
//googleUpdateParentFolder = paramDriveFromFolderName;
//googleUpdateTeamDriveID = paramTeamID;
//googleUpdateFileName = paramFileName;
//googleUpdateFilePath = paramFilePath;
//googleUpdateLocalFolderPath = paramLocalFolderPath;
// HC values for testing
googleUpdateFilePath = "C:\\Path\\to_update_file\\update_file.txt";
googleUpdateLocalFolderPath = "C:\\Path\\to_update_file\\";
googleUpdateFileName = "update_file.txt";
googleUpdateParentFolder = "Folder_on_Google_Drive";
googleUpdateTeamDriveID = "Team_Drive_ID";
googleUpdateParentFolderID = "Parent_Folder_ID";
Console.WriteLine("value of googleUploadFilePath: " + googleUpdateFilePath);
Console.WriteLine("value of googleUploadLocalFolderPath: " + googleUpdateLocalFolderPath);
Console.WriteLine("value of googleUploadFileName: " + googleUpdateFileName);
Console.WriteLine("value of googleUploadParentFolder: " + googleUpdateParentFolder);
Console.WriteLine("value of googleUploadTeamDriveID: " + googleUpdateTeamDriveID);
Console.WriteLine("value of googleUploadParentFolderID: " + googleUpdateParentFolderID);
googleUpdateText = (JsonConvert.SerializeObject(GoogleAPI.GoogleAPI_Drive.GDrive_Update_File(googleUpdateFilePath, googleUpdateLocalFolderPath, googleUpdateFileName, "no description", googleUpdateParentFolder, paramUserID, "", "", googleUpdateTeamDriveID, googleUpdateParentFolderID), Formatting.Indented));
Console.WriteLine("value of googleUpdateText: " + googleUpdateText);
Console.WriteLine("this is the end of the update text");
};
// end
}
// end of Main
}
// end of program class
}
Section 2- This is the middle part of the code that updates files in a list of files which calls each file to update it.
public static String GDrive_Update_File(string pathToFile, string localFilePath, string fileName, string description, string parentFolder = "", string userid = "", string sharedUserIds = "", string sharerole = "", string teamID = "", string parentFolderID = "")
{
FileResponseJSON fileJson = new FileResponseJSON();
List<string> fileArray = new List<string> { };
IList<FileResponseJSON> filesJSON = new List<FileResponseJSON>();
IList<Google.Apis.Drive.v3.Data.File> files = new List<Google.Apis.Drive.v3.Data.File>();
List<string> parents = new List<String> { };
List<string> kids = new List<String> { };
UserCredential credential = GoogleAPI_Functions.GetCredentials(userid);
var service = new DriveService(new BaseClientService.Initializer
{
ApplicationName = APP_NAME,
HttpClientInitializer = credential,
});
if (!String.IsNullOrEmpty(parentFolder))
{
FilesResource.ListRequest listRequest = service.Files.List();
listRequest.Q = String.Format("(name contains '{0}') and (mimeType = 'application/vnd.google-apps.folder')", parentFolder);
listRequest.Fields = "files(*)";
if (teamID.Length > 3)
{
listRequest.SupportsTeamDrives = true; // new
listRequest.Corpora = "teamDrive"; // new
listRequest.IncludeTeamDriveItems = true;//new
listRequest.TeamDriveId = teamID;//new
}
// List files.
IList<Google.Apis.Drive.v3.Data.File> folders = listRequest.Execute().Files;
foreach (var fldr in folders)
{
if (parentFolderID.Length > 3)
{
if (fldr.Id.Equals(parentFolderID))
{
parents.Add(fldr.Id);
}
}
else
{
parents.Add(fldr.Id);
}
Console.WriteLine("value of fldr.Id " + fldr.Id);
}
}
// Upload File MetaData
// mimeType is important and so it the 'trashed' true/false or it won't be found
FilesResource.ListRequest fileRequest = service.Files.List();
string query = "name contains 'update_file.txt' and (mimeType = 'text/plain') and trashed = false";
fileRequest.Q = String.Format(query);
fileRequest.Fields = "files(*)";
fileRequest.SupportsTeamDrives = true; // new
fileRequest.Corpora = "teamDrive"; // new
fileRequest.IncludeTeamDriveItems = true;//new
fileRequest.TeamDriveId = teamID;//new
IList<Google.Apis.Drive.v3.Data.File> myFiles = fileRequest.Execute().Files;
Console.WriteLine("Files:");
if (myFiles != null && myFiles.Count > 0)
{
foreach (var myf in myFiles)
{
myf.Name = localFilePath + myf.Name;
Console.WriteLine("{0} ({1})", myf.Name, myf.Id);
UpdateFile(service, myf.Name, myf.Id);
}
}
else
{
Console.WriteLine("No files found.");
}
Console.Read();
var UpdatedID = "";
return UpdatedID;
}
Section 3- This section is supposed to update each file --> THIS IS THE SECTION WITH THE PROBLEM (The Google.Apis.Drive.v3.Data.File updatedFile always returns null)
public static Google.Apis.Drive.v3.Data.File UpdateFile(DriveService _service, string _uploadFile, string _fileId)
{
Google.Apis.Drive.v3.Data.File file = new Google.Apis.Drive.v3.Data.File();
byte[] byteArray = System.IO.File.ReadAllBytes(_uploadFile);
System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray);
FilesResource.UpdateMediaUpload request = _service.Files.Update(file, _fileId, stream, GetMimeType(_uploadFile));
void Upload_ProgressChanged(IUploadProgress progress) =>
Console.WriteLine(progress.Status + " " + progress.BytesSent);
void Upload_ResponseReceived(Google.Apis.Drive.v3.Data.File myfile) =>
Console.WriteLine(myfile.Name + " was uploaded successfully");
request.ProgressChanged += Upload_ProgressChanged;
request.ResponseReceived += Upload_ResponseReceived;
request.Upload();
Google.Apis.Drive.v3.Data.File updatedFile = request.ResponseBody;
return updatedFile;
}
update: I used IUploadProgress.Exception and got the following error-
Exception: The service drive has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
File not found: 1XYZ..... [404]
Errors [
Message[File not found: 1XYZ.......] Location[fileId - parameter] Reason[notFound] Domain[global]
]
at Google.Apis.Upload.ResumableUpload.<HandleResponse>d__78.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Google.Apis.Upload.ResumableUpload.<SendNextChunkAsync>d__77.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Google.Apis.Upload.ResumableUpload.<UploadCoreAsync>d__74.MoveNext() 0
Update again, I was able to see the uri that was being generated and copy/paste it into the browser, and when I did I got a 405 Method Not Allowed; additionally when I tried it without the https and just used http I got a 403 Forbidden and that SSL is required to perform this operation
This is the uri without the ids
https://www.googleapis.com/upload/drive/v3/files/[file_id]?uploadType=resumable&upload_id=[upload_id]
Update:
During the process the api produces these two urls that both work and allow me access
WebContentLink
"https://drive.google.com/uc?id=[docID]&export=download"
WebViewLink
"https://drive.google.com/file/d/[docID]/view?usp=drivesdk"
Latest update applied fixes from DalmTo but am getting new errors-
// - removed // Google.Apis.Drive.v3.Data.File file = new
// - added //
var fileMetadata = new Google.Apis.Drive.v3.Data.File()
{
Id = _fileId
};
var fsSource = new MemoryStream(Encoding.UTF8.GetBytes(_uploadFile ?? ""));
var request = _service.Files.Update(fileMetadata, fileMetadata.Id, fsSource, GetMimeType(_uploadFile));
New error:
Exception: The service drive has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
The resource body includes fields which are not directly writable. [403]
Errors [
Message[The resource body includes fields which are not directly writable.] Location[ - ] Reason[fieldNotWritable] Domain[global]
]
Not sure what would cause this.
File id is writeable so you should be able to send it with the file metadata in your request.
var fileMetadata = new Google.Apis.Drive.v3.Data.File()
{
Id = "xxx"
};
var fsSource = new MemoryStream(Encoding.UTF8.GetBytes(uploadString ?? ""));
var request = service.Files.Update(fileMetadata, fileMetadata.Id , fsSource, GetMimeType(uploadFilePath));
Update
From comments you are sending an empty metadata file object with your request.
Google.Apis.Drive.v3.Data.File file = new Google.Apis.Drive.v3.Data.File();
There for Drive is always going to give you a new file id. I am sending the original file id as part of the metadata there for it will use the file id.
Here's my code and I have doubt on thread safe implementation. My questions are below
The return value from GetHtmlPageAsync is object. Is it thread safe? I will use this object and add into the collection and finally upload into database.
The main method logic is below (implementation in-progress). I have set of domains, I have list of 10000 domains in the collection, the idea is, I will put it in the queue and call the GetHtmlPageAsync to get the HTML of the page. Based on the HTML, I will get the necessary hyperlinks. Once I get the hyper links, I will check certain word is available in the link. If the word is available in the link, I will call the same method GetHTMLPageAsync to get the HTML of that page. So the same thread may call the GetHtmlPageAsync to process another link. I am trying to reuse the same method for multiple calls in thread safe way. Please help.
#edit1 . I have added the main method. Instead of Queue. I have used ForEach
public static async Task<int> ProcessDomainAsync(List<string> domains)
{
Parallel.ForEach(domains, async (currentDomain) =>
{
var domainBody = await GetHtmlPageAsync(currentDomain);
var language = string.Empty;
var country = string.Empty;
var createdOn = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local);
var updatedOn = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local);
var machine = Environment.MachineName;
var message = "[" + domainBody.ErrorCode + "] - " + domainBody.ErrorMessage;
var active = false;
var stage = "End";
var url = currentDomain;
if (domainBody.ErrorCode == 0)
{
var html = domainBody.Body;
language = Common.GetLanguageIdentification(html);
country = Common.GetCountryIdentification(currentDomain);
message = string.Empty;
active = true;
stage = "Stage1";
var hyperLinks = Common.GetAllAHrefTags(html);
//Process Hyper Links
}
_domainList.Add(new Domain
{
Url = url,
Language = language,
Country = country,
MachineName = machine,
Message = message,
Active = active,
Stage = stage,
CreatedOn = createdOn,
UpdatedOn = updatedOn
});
domainCount++;
});
return domainCount;
}
public class DomainBody
{
public string Body;
public string ErrorMessage;
public int ErrorCode;
}
public static class DomainProcessing {
static async Task<DomainBody> GetHtmlPageAsync(string url)
{
#region Initialize Proxy
var sessionId = new Random().Next().ToString();
var proxy = new WebProxy(Constant.ProxyUrl, Constant.ProxyPort);
var login = Constant.ProxyUserName + "-session-" + sessionId;
proxy.Credentials = new NetworkCredential(login,Constant.ProxyPassword);
#endregion
#region Initialize Variables
var user_agent = Common.GenerateRandomUserAgent();
var body = string.Empty;
var errorCode = 0;
var errorMessage = string.Empty;
#endregion
try
{
#region Format URL with Http Protocol
var domainSB = new StringBuilder();
domainSB.Append("http://");
domainSB.Append(url);
#endregion
#region Process Domain
var request = (HttpWebRequest) WebRequest.Create(new Uri(url));
request.Proxy = proxy;
request.UserAgent = user_agent;
request.Timeout = Constant.TimeOut;
using (var response = await request.GetResponseAsync().ConfigureAwait(true))
using (var content = new MemoryStream())
using (var responseStream = response.GetResponseStream())
{
await responseStream.CopyToAsync(content);
var bodyArray = content.ToArray();
body = Encoding.UTF8.GetString(bodyArray, 0, bodyArray.Length);
}
errorCode = 0;
errorMessage = string.Empty;
#endregion
}
catch (HttpRequestException ex)
{
body = string.Empty;
errorCode = ex.InnerException.HResult;
errorMessage = ex.InnerException.Message;
}
catch (Exception ex)
{
body = string.Empty;
errorCode = ex.HResult;
errorMessage = ex.Message;
}
var domainBody = new DomainBody
{
Body = body,
ErrorCode = errorCode,
ErrorMessage = errorMessage
};
return domainBody;
}
}enter code here
Generally speaking, local variables should be thread safe (simply because they have no idea there even is another thread and other threads have no way to access them).
Anything that can be accessed by multiple threads should be looked at. _domainList for example. Make sure the Add method is thread-safe because you are calling it potentially in parallel.
I would like to implement the Perforce command "Get Revision [Changelist Number]" using the Perforce .NET API (C#). I currently have code that will "Get Latest Revision", but I need to modify it to get a specific changelist.
To sync the data with a changelist number, what should I do?
Source
// --------Connenct----------------
Perforce.P4.Server server = new Perforce.P4.Server(
new Perforce.P4.ServerAddress("127.0.0.1:9999"));
Perforce.P4.Repository rep = new Perforce.P4.Repository(server);
Perforce.P4.Connection con = rep.Connection;
con.UserName = m_P4ID;
string password = m_P4PASS;
Perforce.P4.Options opconnect = new Perforce.P4.Options();
opconnect.Add("-p", password);
con.Connect(opconnect);
if (con.Credential == null)
con.Login(password);
//----------Download----------
string clientPath = #"C:\P4V\";
string ws_client = clientPath;
Perforce.P4.Client client = new Perforce.P4.Client();
client.Name = ws_client;
client.Initialize(con);
con.CommandTimeout = new TimeSpan(0);
IList<Perforce.P4.FileSpec> fileList = client.SyncFiles(new Perforce.P4.Options());
//----------Disconnect------------
con.Disconnect();
con.Dispose();
Edit: Attempt 1
Perforce.P4.DepotPath depot = new Perforce.P4.DepotPath("//P4V//");
Perforce.P4.LocalPath local = new Perforce.P4.LocalPath(ws_client);
Perforce.P4.FileSpec fs = new Perforce.P4.FileSpec(depot, null, local,
Perforce.P4.VersionSpec.Head);
IList<Perforce.P4.FileSpec> listFiles = new List<Perforce.P4.FileSpec>();
listFiles.Add(fs);
IList<Perforce.P4.FileSpec> foundFiles = rep.GetDepotFiles(listFiles,
new Perforce.P4.Options(1234)); // 1234 = Changelist number
client.SyncFiles(foundFiles, null);
Error Message
Usage: files/print [-o localFile -q] files...Invalid option: -c.
I do not know the problem of any argument.
Or there will not be related to this reference source?
Edit 2
I tried to solve this problem. However, it does not solve the problem yet.
Perforce.P4.Changelist changelist = rep.GetChangelist(1234);
IList<Perforce.P4.FileMetaData> fileMeta = changelist.Files;
In this case, I could get only the files in the changelist. I would like to synchronize all files of the client at the moment of changelist 1234.
SyncFiles takes an optional FileSpec arg. You can specify a file path and a revision specifier with that FileSpec arg. Here are the relevant docs:
FileSpec object docs
SyncFiles method docs
You don't need to run GetDepotFiles() to get the FileSpec object; you can just create one directly as shown in the FileSpec object docs. The error you are getting with GetDepotFiles() is because it expects the change number to be specified as part of the FileSpec object passed into as the first argument to GetDepotFiles().
To expand further, GetDepotFiles() calls the 'p4 files' command when it talks to Perforce. new Perforce.P4.Options(1234) generates an option of '-c 1234' which 'p4 files' doesn't accept. That's why the error message is 'Usage: files/print [-o localFile -q] files...Invalid option: -c.'
I struggled with the same problem as well. Finally based on Matt's answer I got it working. Please see simple example below.
using (Connection con = rep.Connection)
{
//setting up client object with viewmap
Client client = new Client();
client.Name = "p4apinet_solution_builder_sample_application_client";
client.OwnerName = "p4username";
client.Root = "c:\\clientRootPath";
client.Options = ClientOption.AllWrite;
client.LineEnd = LineEnd.Local;
client.SubmitOptions = new ClientSubmitOptions(false, SubmitType.RevertUnchanged);
client.ViewMap = new ViewMap();
client.ViewMap.Add("//depotpath/to/your/file.txt", "//" + client.Name + "/clientpath/to/your/file.txt", MapType.Include);
//connecting to p4 and creating client on p4 server
Options options = new Options();
options["Password"] = "p4password";
con.UserName = "p4username";
con.Client = new Client();
con.Connect(options);
con.Client = rep.CreateClient(client);
//syncing all files (in this case 1) defined in client's viewmap to the changelist level of 12345
Options syncFlags = new Options(SyncFilesCmdFlags.Force, 100);
VersionSpec changeListLevel = new ChangelistIdVersion(12345);
List<FileSpec> filesToBeSynced = con.Client.ViewMap.Select<MapEntry, FileSpec>(me => new FileSpec(me.Left, changeListLevel)).ToList();
IList<FileSpec> results = con.Client.SyncFiles(filesToBeSynced, syncFlags);
}
The following code should allow you to sync a depot to a particular revision (changelist number).
string uri = "...";
string user = "...";
string workspace = "...";
string pass = "...";
int id = 12345; // the actual changelist number
string depotPath = "//depot/foo/main/...";
int maxItemsToSync = 10000;
Server server = new Server(new ServerAddress(uri));
Repository rep = new Repository(server);
server = new Server(new ServerAddress(uri));
rep = new Repository(server);
Connection con = rep.Connection;
con.UserName = user;
con.Client = new Client();
con.Client.Name = workspace;
// connect
bool connected = con.Connect(null);
if (connected)
{
try
{
// attempt a login
Perforce.P4.Credential cred = con.Login(pass);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
con.Disconnect();
connected = false;
}
if (connected)
{
// get p4 info and show successful connection
ServerMetaData info = rep.GetServerMetaData(null);
Console.WriteLine("CONNECTED TO " + info.Address.Uri);
Console.WriteLine("");
try
{
Options opts = new Options();
// uncomment below lines to only get a preview of the sync w/o updating the workspace
//SyncFilesCmdOptions syncOpts = new SyncFilesCmdOptions(SyncFilesCmdFlags.Preview, maxItemsToSync);
SyncFilesCmdOptions syncOpts = new SyncFilesCmdOptions(SyncFilesCmdFlags.None, maxItemsToSync);
VersionSpec version = new ChangelistIdVersion(id);
PathSpec path = new DepotPath(depotPath);
FileSpec depotFile = new FileSpec(path, version);
IList<FileSpec> syncedFiles = rep.Connection.Client.SyncFiles(syncOpts, depotFile);
//foreach (var file in syncedFiles)
//{
// Console.WriteLine(file.ToString());
//}
Console.WriteLine($"{syncedFiles.Count} files got synced!");
}
catch (Exception ex)
{
Console.WriteLine("");
Console.WriteLine(ex.Message);
Console.WriteLine("");
}
finally
{
con.Disconnect();
}
}
}
If you are looking for other ways to build the file spec, like for example sync only a specific list of files to "head", etc, visit this link and search for "Building a FileSpec"
I need to create a user control in either vb.net or c# to search a RightNow CRM database. I have the documentation on their XML API, but I'm not sure how to post to their parser and then catch the return data and display it on the page.
Any sample code would be greatly appreciated!
Link to API: http://community.rightnow.com/customer/documentation/integration/82_crm_integration.pdf
I don't know RightNow CRM, but according to the documentation you can send the XML requests using HTTP post. The simplest way to do this in .NET is using the WebClient class. Alternatively you might want to take a look at the HttpWebRequest/HttpWebResponse classes. Here is some sample code using WebClient:
using System.Net;
using System.Text;
using System;
namespace RightNowSample
{
class Program
{
static void Main(string[] args)
{
string serviceUrl = "http://<your_domain>/cgi-bin/<your_interface>.cfg/php/xml_api/parse.php";
WebClient webClient = new WebClient();
string requestXml =
#"<connector>
<function name=""ans_get"">
<parameter name=""args"" type=""pair"">
<pair name=""id"" type=""integer"">33</pair>
<pair name=""sub_tbl"" type='pair'>
<pair name=""tbl_id"" type=""integer"">164</pair>
</pair>
</parameter>
</function>
</connector>";
string secString = "";
string postData = string.Format("xml_doc={0}, sec_string={1}", requestXml, secString);
byte[] postDataBytes = Encoding.UTF8.GetBytes(postData);
byte[] responseDataBytes = webClient.UploadData(serviceUrl, "POST", postDataBytes);
string responseData = Encoding.UTF8.GetString(responseDataBytes);
Console.WriteLine(responseData);
}
}
}
I have no access to RightNow CRM, so I could not test this, but it can serve as s tarting point for you.
This will Create a Contact in Right now
class Program
{
private RightNowSyncPortClient _Service;
public Program()
{
_Service = new RightNowSyncPortClient();
_Service.ClientCredentials.UserName.UserName = "Rightnow UID";
_Service.ClientCredentials.UserName.Password = "Right now password";
}
private Contact Contactinfo()
{
Contact newContact = new Contact();
PersonName personName = new PersonName();
personName.First = "conatctname";
personName.Last = "conatctlastname";
newContact.Name = personName;
Email[] emailArray = new Email[1];
emailArray[0] = new Email();
emailArray[0].action = ActionEnum.add;
emailArray[0].actionSpecified = true;
emailArray[0].Address = "mail#mail.com";
NamedID addressType = new NamedID();
ID addressTypeID = new ID();
addressTypeID.id = 1;
addressType.ID = addressTypeID;
addressType.ID.idSpecified = true;
emailArray[0].AddressType = addressType;
emailArray[0].Invalid = false;
emailArray[0].InvalidSpecified = true;
newContact.Emails = emailArray;
return newContact;
}
public long CreateContact()
{
Contact newContact = Contactinfo();
//Set the application ID in the client info header
ClientInfoHeader clientInfoHeader = new ClientInfoHeader();
clientInfoHeader.AppID = ".NET Getting Started";
//Set the create processing options, allow external events and rules to execute
CreateProcessingOptions createProcessingOptions = new CreateProcessingOptions();
createProcessingOptions.SuppressExternalEvents = false;
createProcessingOptions.SuppressRules = false;
RNObject[] createObjects = new RNObject[] { newContact };
//Invoke the create operation on the RightNow server
RNObject[] createResults = _Service.Create(clientInfoHeader, createObjects, createProcessingOptions);
//We only created a single contact, this will be at index 0 of the results
newContact = createResults[0] as Contact;
return newContact.ID.id;
}
static void Main(string[] args)
{
Program RBSP = new Program();
try
{
long newContactID = RBSP.CreateContact();
System.Console.WriteLine("New Contact Created with ID: " + newContactID);
}
catch (FaultException ex)
{
Console.WriteLine(ex.Code);
Console.WriteLine(ex.Message);
}
System.Console.Read();
}
}