I am attempting to create a .NET program that calls the NetSuite web services to return a list of files associated to a customer.
I have set the ShopperJoin to the customer I've searched for, but the web call still returns all files in the File Cabinet.
FileSearch file = new FileSearch();
CustomerSearchBasic custBasic = new CustomerSearchBasic();
custBasic.entityId= new SearchStringField();
custBasic.entityId.#operator = SearchStringFieldOperator.contains ;
custBasic.entityId.operatorSpecified = true;
file.shopperJoin = custBasic;
file.basic = new FileSearchBasic();custBasic.entityId.searchValue = "ID";
SearchResult result = _service.search(file);
I am using the 2015 SuiteTalk wsdl
https://webservices.na1.netsuite.com/wsdl/v2015_1_0/netsuite.wsdl
Have you checked if the customer id and the folder id are the same? (just a hunch)
After contacting NetSuite support, I learned that I had taken the wrong approach.
Files can be filtered based on customer via a customer search.
I was able to create a CustomerSearchAdvanced request that retrieves associated files.
When you create that, you add the columns you want to the FileJoin object in the request, and it will find the files based on whatever customer criteria you set up.
CustomerSearchAdvanced attachSearch = new CustomerSearchAdvanced();
SearchColumnStringField[] stringcols = new SearchColumnStringField[1];
stringcols[0] = new SearchColumnStringField();
SearchColumnStringField[] stringcols = new SearchColumnStringField[1];
stringcols[0] = new SearchColumnStringField();
attachSearch.columns = new CustomerSearchRow();
attachSearch.columns.fileJoin = new FileSearchRowBasic();
attachSearch.columns.fileJoin.internalId = selcols;
attachSearch.columns.fileJoin.description = stringcols;
attachSearch.columns.fileJoin.name = stringcols;
Related
I'm trying to link a c# application to a sharepoint directory, so I can create folders, download and upload files. However I am strugling with connecting to the correct folder.
I can retrieve the content from allitems.aspx, but I am not sure how to actually get the content from folder.
I have tried using the ClientContext - something like this:
ClientContext cxt = new ClientContext("https://xx.sharepoint.com/sites/");
cxt.Credentials = GetCredentials();
List list = cxt.Web.Lists.GetByTitle("Kontrakter");
var test = list.Views;
var test1 = cxt.Web.Lists;
cxt.Load(test1);
cxt.Load(list);
cxt.Load(test);
var a = 4;
var fullUri = new Uri("https://xx.sharepoint.com/sites/yy/Kontrakter/AllItems.aspx");
//var folder = cxt.Web.GetFolderByServerRelativeUrl(fullUri.AbsolutePath);
using (var rootCtx = new ClientContext(fullUri.GetLeftPart(UriPartial.Authority)))
{
rootCtx.Credentials = GetCredentials();
Uri webUri = Web.WebUrlFromPageUrlDirect(rootCtx, fullUri);
using (var ctx1 = new ClientContext(webUri))
{
ctx1.Credentials = GetCredentials();
var list1 = ctx1.Web.GetList(fullUri.AbsolutePath);
ctx1.Load(list1.RootFolder.Files);
ctx1.ExecuteQuery();
Console.WriteLine(list.RootFolder.Files.Count);
}
}
or via normal api calls like this:
https://xx.sharepoint.com/_api/Web/GetFolderByServerRelativeUrl('Kontrakter/Forms')/Files
The only way I can find some data is if I look into 'Shared documents/Forms'
I'm having problems understanding the directory structure and how I can actually find the content of files/folders.
Thanks in advance :)
Turned out I was missing a /sites in one of my uris.
i could successfully add bugs into TFS programmatically,
var tfsURI = new Uri("http://test:8080/tfs");
var networkCredential1 = new NetworkCredential("test", "test!");
ICredentials credential = (ICredentials)networkCredential1;
Microsoft.VisualStudio.Services.Common.WindowsCredential winCred = new Microsoft.VisualStudio.Services.Common.WindowsCredential(credential);
VssCredentials vssCredentials = new VssCredentials(winCred);
using (TfsTeamProjectCollection collection = new TfsTeamProjectCollection(tfsURI, vssCredentials))
{
collection.EnsureAuthenticated();
WorkItemStore workItemStore = collection.GetService<WorkItemStore>();
Project teamProject = workItemStore.Projects["Test"];
WorkItemType workItemType = teamProject.WorkItemTypes["Bug"];
WorkItem Defect = new WorkItem(workItemType);
FileInfo fi = new FileInfo(#"C:\\Document.docx");
Attachment tfsAttachment = new Attachment(fi.FullName);
Defect.Attachments.Add(tfsAttachment);
Defect.Title = "Testing from VS to TFS Bug";
Defect.Description = "Testing from VS to entered Bug in to TFS.";
Defect.Fields["Assigned To"].Value = "Test";
Defect.Save();
}
I have Newly Created WorkItem ID. Defect.ID provides me workitemID.
How can i get the URL of newly created WOrkItem by passing ID.
Let Me know if any API available? i need HTML Link of Newly created WorkItem so that anyone when click on URL, created WorkItem will be Open.
You could use Rest API to directly return a single work item
GET https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/{id}?api-version=5.1
However this will only get a url to the json data for the bug created, not the URL of the HTML page of the bug. Such as below output that I got
https://tfsurl:8080/_apis/wit/workItems/workitemID
When I load the above link in browser, I got JSON data, instead of the HTML page for the work item I created.
Guess you want to fetch the url of HTML in web portal.
https://tfsurl:8080/tfs/DefaultCollection/PatrickProject/_workitems/edit/172/
In my case it was this and here DefaultCollection is the collection name and the PatrickProject is the project name. I used this url and got rid of the id '172' in this case and use the ID of newly created work item. This would return the URL to go to the work item HTML page.
So it's a fixed format, if you have Newly Created WorkItem ID and collection name , project name, you just need to follow above format and change the last value of work item ID. That's it , ignore of which work item type you created.
Hope this Helps!
I found solution after lots of research, may help to someone in future:
var tfsURI = new Uri("http://test:8080/tfs");
var networkCredential1 = new NetworkCredential("test", "test!");
ICredentials credential = (ICredentials)networkCredential1;
Microsoft.VisualStudio.Services.Common.WindowsCredential winCred = new Microsoft.VisualStudio.Services.Common.WindowsCredential(credential);
VssCredentials vssCredentials = new VssCredentials(winCred);
using (TfsTeamProjectCollection collection = new TfsTeamProjectCollection(tfsURI, vssCredentials))
{
collection.EnsureAuthenticated();
TswaClientHyperlinkService hyperlinkService =
collection.GetService<TswaClientHyperlinkService>();
String TFSurl = hyperlinkService.GetWorkItemEditorUrl(17648).ToString(); //17648 WorkItem ID
}
I have a SharePoint Online where I can connect through my console application successfully:
private static ClientContext GetUserContext()
{
var o365SecurePassword = new SecureString();
foreach (char c in o365Password)
{
o365SecurePassword.AppendChar(c);
}
var o365Credentials = new SharePointOnlineCredentials(o365Username, o365SecurePassword);
var o365Context = new ClientContext(o365SiteUrl);
o365Context.Credentials = o365Credentials;
return o365Context;
}
But what I need now to do is to go into my SharePoint Document Library named "doc_archive" and check if there exists a folder with name "K20170409-01".
If not create a new one.
Failed Attempt
ClientContext context = GetUserContext();
Web web = context.Web;
Web webroot = context.Site.RootWeb;
context.Load(web);
context.Load(webroot);
List list = webroot.GetList("doc_archive");
context.Load(list);
FolderCollection folders = list.RootFolder.Folders;
context.Load(folders);
IEnumerable<Folder> existingFolders = context.LoadQuery(
folders.Include(
folder => folder.Name)
);
context.ExecuteQuery();
What is the fastest ways to check and create a folder within a document library in SharePoint Online via CSOM (commandline application)?
If you are happy with using external libraries then the OfficeDevPnP.Core has some great CSOM extensions for SharePoint and SharePoint Online. It's readily available as a NuGet package to add to your projects.
For your requirment there is the EnsureFolderPath extension. This function will check if a folder exists, create it if needed and return the Microsoft.SharePoint.Client.Folder object.
Very easy to use:
var webRelativeUrlToFolder = "/doc_archive/K20170409-01"
var folder = cc.Web.EnsureFolderPath(webRelativeUrlToFolder);
cc.Load(folder);
cc.ExecuteQuery();
I can't vouch for how fast this would be, but it works in the end on 0365. Note that it throws a ServerException if the target already exists.
using (var ctx = new ClientContext(siteUrl))
{
ctx.Credentials = new SharePointOnlineCredentials(username, securePwd);
var list = new ListCreationInformation()
{
Title = title
Description = "User Created Document Library",
TemplateType = asDocumentLibrary ? 101 : 100 // 100 is a custom list.
};
ctx.Web.Lists.Add(list);
ctx.ExecuteQuery();
success = true;
}
Most CSOM examples are found in Powershell. The process in C# CSOM is actually the same, so next time find a Powershell example when a C# one is not available.
I have a small C# console application who's sole purpose is to receive records from a "Saved Search" in NetSuite(via SuiteTalk). I've been able to successfully connect and receive records from NetSuite for my Saved Search(the search runs fine through the web interface too), however when I attempt to access the results of the "Saved Search" through my application, I am unable to view them because the search object that is returned does not contain any data in the "recordList" property:
//Connect
var dataCenterAwareNetSuiteService = new DataCenterAwareNetSuiteService("XXXXXX");
dataCenterAwareNetSuiteService.Timeout = 1000 * 60 * 60 * 2;
//Adds Credentials etc...
dataCenterAwareNetSuiteService.tokenPassport = createTokenPassport();
//Setup Preferences
var prefs = new Preferences();
prefs.warningAsErrorSpecified = true;
prefs.warningAsError = false;
dataCenterAwareNetSuiteService.preferences = prefs;
var searchPrefs = new SearchPreferences();
dataCenterAwareNetSuiteService.searchPreferences = searchPrefs;
dataCenterAwareNetSuiteService.searchPreferences.pageSize = 5;
dataCenterAwareNetSuiteService.searchPreferences.pageSizeSpecified = true;
dataCenterAwareNetSuiteService.searchPreferences.bodyFieldsOnly = false;
dataCenterAwareNetSuiteService.searchPreferences.returnSearchColumns = false;
//Search
var tranSearchAdv = new TransactionSearchAdvanced();
var tranSearchRow = new TransactionSearchRow();
var tranSearchRowBasic = new TransactionSearchRowBasic();
tranSearchAdv.savedSearchId = "XXXX";
tranSearchRowBasic.internalId =
new SearchColumnSelectField[] { new SearchColumnSelectField() };
tranSearchRowBasic.tranId =
new SearchColumnStringField[] { new SearchColumnStringField() };
tranSearchRowBasic.dateCreated =
new SearchColumnDateField[] { new SearchColumnDateField() };
tranSearchRowBasic.total =
new SearchColumnDoubleField[] { new SearchColumnDoubleField() };
tranSearchRowBasic.entity =
new SearchColumnSelectField[] { new SearchColumnSelectField() };
tranSearchRow.basic = tranSearchRowBasic;
tranSearchAdv.columns = tranSearchRow;
//No errors,
//this works correctly and returns the "Saved Search" with the correct "totalRecords"
//but results.recordList == null while results.totalRecords = 10000000+
var results = dataCenterAwareNetSuiteService.search(tranSearchAdv);
I appears to me that the "recordList" object is the principal way data is retrieved from the results of a search(Related Java Example, Another Here). This is also the way the example API does it.
I have run this on multiple "Saved Search's" with the same results. I don't understand how you can have more than one record in "totalRecords" and yet the "recordList" remains null? Is there some configuration option that has to be set to allow me to access this property. Or maybe it's a security thing, the API user I have setup should have full access, is there anything else that need to be granted access?
NetSuite SuiteTalk is not well documented, and most of the examples online are not in C#, and not dealing with the issues that I'm experiencing. These factors make it very difficult to determine why the previously mentioned behavior is occurring, or even, to discover any alternative methods for retrieving the resulting data from the source "Saved Search".
Does anyone have any insight into this behavior? Is this the correct method of retrieving results from SuiteTalk? Is there any configuration from the API or Web Side that needs to be changed?
Update 1
I've also tried using the alternative way of getting result data by accessing the "searchRowList" object from the "SearchResult" object(suggested by #AdolfoGarza) However it returns mostly empty fields(null) similar to the "recordList" property I do not see a way to retrieve "Saved Search" data from this method.
Try getting the results with results.searchRowList.searchRow , thats how it works in php.
I was able to resolve the issue by removing this line in the code:
tranSearchRow.basic = tranSearchRowBasic;
Then like #AdolfoGarza reccomended, retrieving the results from "basic" field in "results.searchRowList"
For some reason the template API that I was using was setting up a "TransactionSearchAdvanced" referencing a blank "TransactionSearchBasic" record, not sure why but this was causing the results from "searchRowList" to be null. After removing it I now get non-null values in the proper fields.
As for "recordList", it's still null, not sure why, but as I have my data I don't think I'll continue to dig into this.
I have seen example of creating Accounts Entity records, Contacts entity records through C#, i wanted to know how do we create a service record in CRM through C#(.net) code.
Eg: We already have "Plumbing service" record in service entity view. So i wanted to create a new record in service entity through C# code (early or late binding doesn't matter).
Can someone help me on this with code.
Quite some XML is required when creating this Services from code. Additionally, before you can create a Service you will need to create a ResourceSpec and a ConstraintBasedGroup.
First create a ConstraintBasedGroup:
var bu = context.BusinessUnitSet.First().ToEntityReference();
var cbg = new ConstraintBasedGroup
{
BusinessUnitId = bu,
Name = "CBG1",
Constraints = "<Constraints><Constraint><Expression><Body>false</Body><Parameters><Parameter name=\"resource\"/></Parameters></Expression></Constraint></Constraints>"
};
var cbgId = OrganizationService.Create(cbg);
Then create a ResourceSpec:
var resSpec = new ResourceSpec
{
BusinessUnitId = bu,
Name = "RS1",
RequiredCount = 1,
ObjectiveExpression = "<Expression><Body>udf\"Random\"(factory,resource,appointment,request,leftoffset,rightoffset)</Body><Parameters><Parameter name=\"factory\"/><Parameter name=\"resource\"/><Parameter name=\"appointment\"/><Parameter name=\"request\"/><Parameter name=\"leftoffset\"/><Parameter name=\"rightoffset\"/></Parameters><Properties EvaluationInterval=\"P0D\" evaluationcost=\"0\"/></Expression>",
GroupObjectId = cbgId
};
var resSpecId = OrganizationService.Create(resSpec);
And finally, you can create your Service:
var svc = new Service
{
Name = "Service1",
Granularity = "FREQ=MINUTELY;INTERVAL=15",
ResourceSpecId = new EntityReference(ResourceSpec.EntityLogicalName, resSpecId),
InitialStatusCode = new OptionSetValue(0),
Duration = 15
};
OrganizationService.Create(svc);
I would suggest you create similar things using the UI of CRM in case you are wondering about the specific formats of the XML you require. The XML I used in my examples is pretty much the default XML CRM generates.