So here's the case: I am trying to create a Task WorkItem. I have to get the data from a dataGridView, which I think I managed to. But the fun part comes when I try to save, or validate the WorkItem. No matter what value State has, the validator always comes with InvalidListValue on execution of wiTask.Validate();. I have tried even hard-coding the State's value, but nothing happens. There is one thing that bothers me a bit - in the Validation array the error comes within the Status property, where the actual control has only State available. Here are some code and a snippet of the error bit:
WorkItem wiTask = new WorkItem(workItemType)
{
Title = form1.dg_taskView.Rows[rows].Cells["titleDataGridViewTextBoxColumn"].Value.ToString() + " " + form1.tb_details.Text,
Description = form1.dg_taskView.Rows[rows].Cells["descriptionDataGridViewTextBoxColumn"].Value.ToString(),
AreaId = int.Parse(form1.dg_taskView.Rows[rows].Cells["areaIDDataGridViewTextBoxColumn"].Value.ToString()),
AreaPath = form1.dg_taskView.Rows[rows].Cells["areaPathDataGridViewTextBoxColumn"].Value.ToString(),
IterationId = int.Parse(form1.dg_taskView.Rows[rows].Cells["iterationIDDataGridViewTextBoxColumn"].Value.ToString()),
IterationPath = form1.dg_taskView.Rows[rows].Cells["iterationPathDataGridViewTextBoxColumn"].Value.ToString(),
State = form1.dg_taskView.Rows[rows].Cells["stateDataGridViewTextBoxColumn"].Value.ToString()
};
ArrayList result = wiTask.Validate();
wiTask.Save();
var hierarchicalLink = _workItemStore.WorkItemLinkTypes["System.LinkTypes.Hierarchy"];
userStory.WorkItemLinks.Add(new WorkItemLink(hierarchicalLink.ForwardEnd, wiTask.Id));
userStory.Save();
As it turns - the validation returns to the array the column that has issues. After further examination the issue is resolved by specifying to Assigned to name, which is part of the project contributors' list.
Related
I am trying to save a setting in Kentico and I get this error:
The settings key with code name 'AvalaraOrderStatus' already exists.
I already created the setting and I have saved a value to it. The code worked fine in Kentico 8, but I was asked for no SiteInfiIdentifer.
Here is the code I created to make the setting:
//if the setting does not exist, then create it
if (SettingsKeyInfoProvider.GetSettingsKeyInfo(siteName + ".AvalaraOrderStatus", siteID) == null)
{
// Create and set up new SettingsKey
SettingsKeyInfo si = new SettingsKeyInfo();
si.KeyName = "AvalaraOrderStatus";
si.KeyDisplayName = "Avalara Order Status";
si.KeyDescription = "Avalara order status for this site";
si.KeyType = "string";
si.KeyValue = string.Empty;
si.KeyCategoryID = category.CategoryID;
SettingsKeyInfoProvider.SetSettingsKeyInfo(si);
}
The code throws the error on the last line. Here is my code:
int currentSiteID = CMS.SiteProvider.SiteContext.CurrentSiteID;
SiteInfoIdentifier siteId = new SiteInfoIdentifier(currentSiteID);
//update settings in system
SettingsKeyInfoProvider.SetValue(siteName + ".AvalaraOrderStatus", siteId, orderStatus.Trim());
A few things to note:
The first parameter of the SettingsKeyInfoProvider.GetSettingsKeyInfo method does not need to be prefixed with the site name. This is why a site identifier is provided (in your case, the SiteID). Otherwise, you might be getting a null value every time the if statement evaluates, which is why the setting key is being recreated even if it exists. So that should be:
SettingsKeyInfoProvider.GetSettingsKeyInfo("AvalaraOrderStatus", siteID)
The same applies for the SettingsKeyInfoProvider.SetValue method - no need to prefix the site name:
SettingsKeyInfoProvider.SetValue("AvalaraOrderStatus", siteId, orderStatus.Trim())
The CurrentSiteID integer is a valid SiteIdentifier, so there is no need to explicitly instantiate a SiteInfoIdentifier object:
SettingsKeyInfoProvider.SetValue("AlavaraOrderStatus", CMS.SiteProvider.SiteContext.CurrentSiteID, orderStatus.Trim())
I am posting this because it might help someone using the VersionOne API SDK Client. I wanted to change the status of a test programmatically, to one of the following categories: Ready, InTesting, Passed, or Failed. I originally tried to change the attribute 'Status.Name' however I would get an error that the attribute is a Read-Only attribute. Another suggestion was to create a new attribute with the same name and that the new attribute would override the previous read-only attribute with the same name. However, it appears that I was looking at it backwards.
internal void TestStatusPassed(string str_TestID)
{
var testId = Oid.FromToken(str_TestID, _context.MetaModel);
var query = new Query(testId);
var testType = _context.MetaModel.GetAssetType("Test");
var sourceAttribute = testType.GetAttributeDefinition("Status.Name");
query.Selection.Add(sourceAttribute);
var result = _context.Services.Retrieve(query);
var test = result.Assets[0];
var oldSource = GetValue(test.GetAttribute(sourceAttribute).Value);
test.SetAttributeValue(sourceAttribute, "Passed");
_context.Services.Save(test);
}
This code will throw an exception "Cannot change a read-only attribute"...
I pulled the XML data for one test from the VersionOne Rest API and noticed a relation named "TestStatus" and then it had a number '9123' assigned to it. So I moved that test manually to 'In Testing' and the "TestStatus" changed to '9121'. Then I moved it to failed and the "TestStatus" changed to '155'. I repeated this with several tests from different testsets and noticed that the numbers for each status were consistent and then changed the code slightly and then I was able to programmatically change the status of each test. I changed "Status.Name" to "Status" and "Passed" to "TestStatus:9123" and now it moves the test into the passed category programmatically.
internal void TestStatusPassed(string str_TestID)
{
var testId = Oid.FromToken(str_TestID, _context.MetaModel);
var query = new Query(testId);
var testType = _context.MetaModel.GetAssetType("Test");
var sourceAttribute = testType.GetAttributeDefinition("Status");
query.Selection.Add(sourceAttribute);
var result = _context.Services.Retrieve(query);
var test = result.Assets[0];
var oldSource = GetValue(test.GetAttribute(sourceAttribute).Value);
test.SetAttributeValue(sourceAttribute, "TestStatus:9123");
_context.Services.Save(test);
}
I am trying to update the "ModifiedBy" field in a Sharepoint discussion board using the Client Object Model. By changing the "Editor" and "Author" fields, I can change the "ModifiedBy" that appears on the list view. However, once you click on a discussion post, the "ModifiedBy" field that appears there (the one with the picture above it) does not reflect the changes. After experimenting, I discovered that the field I need to change to correct this is called "MyEditor". Unfortunately, this field is read-only.
In the code below, I try to change the read-only settings of the field to false. When I look at the MyEditor field in Visual Studio's debugger after the ExecuteQuery() line at the bottom of the first block, it shows that the ReadOnlyField value has in fact been set to false.
sharepointContext.Load(discussionList);
sharepointContext.ExecuteQuery();
var fields = discussionList.Fields;
sharepointContext.Load(fields);
sharepointContext.ExecuteQuery();
var field = fields.GetByInternalNameOrTitle("MyEditor");
field.ReadOnlyField = false;
field.Update();
sharepointContext.Load(field);
sharepointContext.ExecuteQuery();
The code above executes with no problems. The problem comes with this next block:
//...Code to initialize discussionItem...
discussionItem["MyEditor"] = 0;
discussionItem["Editor"] = 0;
discussionItem["Author"] = 0;
discussionItem["Body"] = "Testing";
discussionItem["Title"] = "Hello Worlds";
discussionItem.Update();
sharepointContext.Load(discussionItem);
sharepointContext.ExecuteQuery();
When the code reaches the ExecuteQuery() at the bottom of the second block, it throws a ServerException with the following message:
Invalid data has been used to update the list item.
The field you are trying to update may be read only.
To make sure that the MyEditor field was the one causing the exception to be thrown, I commented out the line where I set it and ran the code again. Everything worked fine. I don't understand what is wrong, can someone help me?
In case someone needs to find the user by name, it goes like this:
private static FieldUserValue GetUser(ClientContext clientContext, string userName)
{
var userValue = new FieldUserValue();
var newUser = clientContext.Web.EnsureUser(userName);
clientContext.Load(newUser);
clientContext.ExecuteQuery();
userValue.LookupId = newUser.Id;
return userValue;
}
The returned value can be set via item["Author"]
ModifiedBy and CreadtedBy calculated automatically from Author and Editor you need to change only Author and Editor fields like this:
using (var clientContext = new ClientContext(#"http://server"))
{
var web = clientContext.Web;
var lst = web.Lists.GetByTitle("Discus");
var item = lst.GetItemById(2);
item["Author"] = 3;
item["Editor"] = 2;
item.Update();
clientContext.ExecuteQuery();
Console.WriteLine("done");
}
I have been trying to create an application to go through our database at a set interval and update/add any new items to 3DCarts database. Their code example uses soap in an xml file to send 1 request per call. So I need to to be able to generate the xml I need with the items information on the fly before sending it. I have done hardly anything with XML files like this and cannot figure out how to create the chunk of code I need and send it. One method that has been suggested is create a file but still executing has been a problem and would be very inefficient for a large number of items. Here is what I have so far
sqlStatement = "SELECT * FROM products WHERE name = '" + Convert.ToString(reader.GetValue(0)) + "'";
ServiceReferenceCart.cartAPIAdvancedSoapClient bcsClient = new ServiceReferenceCart.cartAPIAdvancedSoapClient();
ServiceReferenceCart.runQueryResponse bcsResponse = new ServiceReferenceCart.runQueryResponse();
bcsClient.runQuery(storeUrl, userKey, sqlStatement, callBackURL);
string result = Convert.ToString(bcsResponse);
listBox1.Items.Add(result);
EDIT: Changed from sample code block to current code block as I got a service reference setup finally. They provide no details though for using the functions in the reference. With this bcsResponse is just a blank, when I try adding .Body I have the same result but when I add .runQuery to the .Body I get a "Object reference not set to an instance of an object." error. As I have said I have not messed with service references before.
I hope I have explained well enough I just really have not worked with this kind of stuff before and it has become extremely frustrating.
Thank you in advance for any assistance.
I actually ended up figuring this out after playing around with it. Here is what I did to get the reference to work. This may have been easy for anyone who have used the references before but I have not and have decided to post this in case anyone else has this problem. The SQL can be SELECT, ADD, UPDATE and DELETE statements this was to see if the sku was listed before updating/adding.
//Will be using these multiple times so a variable makes more sense
// DO NOT include http:// in the url, also id is not shown in their
//database layout pdf they will give but it is the sku/product number
string sqlStatement = "SELECT id FROM products WHERE id = '" + Convert.ToString(reader.GetValue(0)) + "')))";
string userKey = "YourKeyHere";
string storeUrl = "YourStoresURLHere";
// Setting up instances from the 3DCart API
cartAPIAdvancedSoapClient bcsClient = new cartAPIAdvancedSoapClient();
runQueryRequest bcsRequest = new runQueryRequest();
runQueryResponse bcsResponse = new runQueryResponse();
runQueryResponseBody bcsRespBod = new runQueryResponseBody();
runQueryRequestBody bcsReqBod = new runQueryRequestBody();
//assigning required variables to the requests body
bcsReqBod.storeUrl = storeUrl;
bcsReqBod.sqlStatement = sqlStatement;
bcsReqBod.userKey = userKey;
//assigning the body to the request
bcsRequest.Body = bcsReqBod;
//Setting the response body to be the result
bcsRespBod.runQueryResult = bcsClient.runQuery(bcsReqBod.storeUrl, bcsReqBod.userKey, bcsReqBod.sqlStatement, bcsReqBod.callBackURL );
bcsResponse.Body = bcsRespBod;
//adding the result to a string
string result = bcsResponse.Body.runQueryResult.Value;
//displaying the string, this for me was more of a test
listBox1.Items.Add(result);
You will also need to activate the Advanced API on your shop as you may notice there is no actual option as the pdf's say, you need to go to their store and purchase(its free) and wait for them to activate it. This took about 2 hrs for us.
We are working on implementing some custom code on a workflow in a Sitecore 6.2 site. Our workflow currently looks something like the following:
Our goal is simple: email the submitter whether their content revision was approved or rejected in the "Awaiting Approval" step along with the comments that the reviewer made. To accomplish this we are adding an action under the "Approve" and "Reject" steps like so:
We are having two big issues in trying to write this code
There doesn't seem to be any easy way to determine which Command was chosen (the workaround would be to pass an argument in the action step but I'd much rather detect which was chosen)
I can't seem to get the comments within this workflow state (I can get them is the next state though)
For further context, here is the code that I have so far:
var contentItem = args.DataItem;
var contentDatabase = contentItem.Database;
var contentWorkflow = contentDatabase.WorkflowProvider.GetWorkflow(contentItem);
var contentHistory = contentWorkflow.GetHistory(contentItem);
//Get the workflow history so that we can email the last person in that chain.
if (contentHistory.Length > 0)
{
//contentWorkflow.GetCommands
var status = contentWorkflow.GetState(contentHistory[contentHistory.Length - 1].NewState);
//submitting user (string)
string lastUser = contentHistory[contentHistory.Length - 1].User;
//approve/reject comments
var message = contentHistory[contentHistory.Length - 1].Text;
//sitecore user (so we can get email address)
var submittingUser = sc.Security.Accounts.User.FromName(lastUser, false);
}
I ended up with the following code. I still see no good way to differentiate between commands but have instead implemented two separate classes (one for approve, one for reject):
public void Process(WorkflowPipelineArgs args)
{
//all variables get initialized
string contentPath = args.DataItem.Paths.ContentPath;
var contentItem = args.DataItem;
var contentWorkflow = contentItem.Database.WorkflowProvider.GetWorkflow(contentItem);
var contentHistory = contentWorkflow.GetHistory(contentItem);
var status = "Approved";
var subject = "Item approved in workflow: ";
var message = "The above item was approved in workflow.";
var comments = args.Comments;
//Get the workflow history so that we can email the last person in that chain.
if (contentHistory.Length > 0)
{
//submitting user (string)
string lastUser = contentHistory[contentHistory.Length - 1].User;
var submittingUser = Sitecore.Security.Accounts.User.FromName(lastUser, false);
//send email however you like (we use postmark, for example)
//submittingUser.Profile.Email
}
}
I have answered a very similar question.
Basically you need to get the Mail Workflow Action and then you need to further extend it to use the original's submitter's email.
Easiest way to get the command item itself is ProcessorItem.InnerItem.Parent
This will give you the GUID for commands like submit, reject etc.
args.CommandItem.ID
This will give you the GUID for states like Draft, approved etc.
args.CommandItem.ParentID