How to Add Custom Fields on JoeBlogs Wordpress Wrapper - c#

I'm trying to complete fields with JoeBlogs WordPress Wrapper.
My code is:
private void postToWordpress(string title, string postContent,string tags, string aioTitle)
{
string link = this.maskedTextBox1.Text;
string username = this.maskedTextBox2.Text;
string password = this.maskedTextBox3.Text;
var wp = new WordPressWrapper(link + "/xmlrpc.php", username, password);
var post = new Post();
post.Title = title;
post.Body = postContent;
post.Tags = tags.Split(',');
string[] cf = new CustomField(); //{ ID = "name", Key = "aiosp_title", Value = "All in One SEO Title" };
cf.ID = "name";
cf.Key = "aiosp_title";
cf.Value = "All in One SEO Title";
post.CustomFields[0] = cf;
wp.NewPost(post, false);
}
The error is at this line:
post.CustomFields[0] = cf;
And it is:
An unhandled exception of type 'System.NullReferenceException'
occurred in JoeBlogsWordpressWrapperTests.exe
Additional information: Object reference not set to an instance of an
object.
So, how to use/add correctly custom fields on WordPress from C# Application using JoeBlogs WordPress Wrapper?

The following code fixes your NullReferenceException and also successfully saves the custom fields into the Post in Wordpress.
private void postToWordpress(string title, string postContent,string tags, string aioTitle)
{
string link = this.maskedTextBox1.Text;
string username = this.maskedTextBox2.Text;
string password = this.maskedTextBox3.Text;
var wp = new WordPressWrapper(link + "/xmlrpc.php", username, password);
var post = new Post();
post.Title = title;
post.Body = postContent;
post.Tags = tags.Split(',');
var cfs = new CustomField[]
{
new CustomField()
{
// Don't pass in ID. It's auto assigned for new custom fields.
// ID = "name",
Key = "aiosp_title",
Value = "All in One SEO Title"
}
};
post.CustomFields = cfs;
wp.NewPost(post, false);
}
You were getting the NullReferenceException error because you were creating a string array and trying to assign it the CustomFields property of the Post object, which is an array of CustomField i.e. CustomField[].
Also, in order to save the CustomFields to the Post in the database, you should pass in only the Key and Value fields of the CustomField struct and skip the ID field all together. Reason being Wordpress auto-generates the ID fields (also it's an integer / numeric field in the database). I think that was what was causing the XmlRpc call to fail, but we did not get any errors as to why.
Try the above code and it should work (I have it working on my localhost WAMP Wordpress installation).
One final note. Although the CustomField's name property is called Key, it doesn't have to be unique, and uniqueness is not enforced. So for instance, if you are populating a custom dropdown box with a list of cities for a Post, you could have the list of cities as a set of custom fields as follows.
var cfs = new CustomField[]
{
new CustomField()
{
Key = "aiosp_title",
Value = "All in One SEO Title"
} ,
new CustomField()
{
Key = "this is another custom field with HTML",
Value = "All in One SEO Title <br/> Keyword 1 <br/><p>This is some more text and html</p>"
} ,
new CustomField()
{
Key = "list_of_cities",
Value = "San Francisco"
} ,
new CustomField()
{
Key = "list_of_cities",
Value = "New York"
}
};
This will also get saved to the post, with 2 custom fields with the same Key value and different text in the Value field's value.
And last but not least, you can store HTML also in the custom fields (as shown above).

Related

How to send multi-select attribute values to Acumatica

I can't find an example of this here or in the Acumatica sample code. Sending single attribute values works fine, but I can't find a way to send multi-select ones. They are returned as a comma-separated list in a string value, but sending them that way doesn't work. Also, sending them as multiple instances of single values doesn't work.
Here's what I've tried. (In the actual code I'm sending some other single attributes in the list, as well, but those work fine.)
// this results in nothing being set for the attribute
string interestedIn = "Brochure, Contact, Collecting small stones";
List<Acumatica.AttributeDetail> attributes = new List<Acumatica.AttributeDetail>();
attributes.Add(
new Acumatica.AttributeDetail {
Attribute = new Acumatica.StringValue { Value = "Interested in" },
Value = new Acumatica.StringValue { Value = interestIn }
}
);
custAdd.Attributes = attributes.ToArray();
// this results in the last item in the list being set for the attribute
string interestedIn = "Brochure, Contact, Collecting small stones";
List<Acumatica.AttributeDetail> attributes = new List<Acumatica.AttributeDetail>();
string[] interests = Convert.ToString(interestedIn).Split(',');
foreach (string interest in interests) {
attributes.Add(
new Acumatica.AttributeDetail {
Attribute = new Acumatica.StringValue { Value = "Interested in" },
Value = new Acumatica.StringValue { Value = interest.Trim() }
}
);
};
custAdd.Attributes = attributes.ToArray();
From the source
MappedCustomer obj = bucket.Customer;
Core.API.Customer impl = obj.Local;
impl.Attributes = impl.Attributes ?? new List<AttributeValue>();
AttributeValue attribute = new AttributeValue();
attribute.AttributeID = new StringValue() { Value = attributeID };
attribute.ValueDescription = new StringValue() { Value = attributeValue?.ToString() };
impl.Attributes.Add(attribute);
Some subtle differences here. Also, I wonder if the .ToArray() call is necessary.

Custom fields with spaces in Workfront issues

Please, can you help me create/update items from custom fields that have space within their name?
We have a project with a custom field Contact phone. This field can be used correctly from the browser. https://github.com/Workfront/workfront-api-examples-csharp didn't help. I was able to add the data within the details of the issue. I would like to add it within the specific custom field (create/update).
var client = new AtTaskRestClient(_url); // from the example
...
var description = $"Contact phone: {item.ContactPhone}";
client.Create(ObjCode.ISSUE, new { name = item.Name,
description = description,
projectID = _projectID });
client.Create has an object as final parameter. We use an anonymous type that can't contain "DE:Contact phone" = item.ContactPhone within the constructor. How can we write this field?
Reading DE:Contact phone works correctly if we insert the value from the browser:
JToken issues = client.Search(ObjCode.ISSUE, new { projectID = _projectID });
foreach (var issue in issues["data"].Children()) {
var name = issue.Value<string>("name"); // correct
var id = issue.Value<string>("ID"); // correct
var fields = client.Get(ObjCode.ISSUE, id, new[] { "description", "DE:Contact phone"}); // correct
https://github.com/Workfront/workfront-api-examples-csharp/blob/master/AtTaskRestExample/AtTaskRestClient.cs
public JToken Create(ObjCode objcode, object parameters) {
VerifySignedIn();
string[] p = parameterObjectToStringArray(parameters, "sessionID=" + SessionID);
JToken json = client.DoPost(string.Format("/{0}", objcode), p);
return json;
}
I wrote a new function CreateEx, that receives a string array
public JToken Create(ObjCode objcode, string[] parameters) {
VerifySignedIn();
JToken json = client.DoPost(string.Format("/{0}", objcode), parameters);
return json;
}
It is accessed as follows:
var client = new AtTaskRestClient(_url); // from the example
...
string[] parameteres =
{
$"name={issueName}",
$"description={description}",
$"projectID={_projectID}",
$"sessionID={client.SessionID}",
$"DE:Contact phone={contactPhone}"
};
client.CreateEx(ObjCode.ISSUE, parameteres);

NetSuite SuiteTalk Joined Search on Custom Objects

I have two custom objects. The parent object is an Order, and it has a list of type Part associated with it. I'm trying to get the list of Parts with a value "Inventory Item" in one field, but only for a particular Order.
I have the name and numeric internalId of the Order available,but the problem is those aren't (as far as I can tell) searchable "fields", there is no "internalId" to provide to tell it to search on one of those.
In the code below, if I don't include the attempt to search on the Order it works fine. I can get all the Parts with a type of "Inventory Item".
I think I need to use a joined search? My attempt at it is below. This produces a SOAP error at runtime:
Additional information: org.xml.sax.SAXException: 'customizationRef' on
{urn:common_2015_1.platform.webservices.netsuite.com}CustomSearchJoin is
required
Code
private static SearchResult NetSuiteSearchOrderItems(NetSuiteService netSuiteService, string order_name, string order_internalId)
{
CustomRecordSearch searchParts = new CustomRecordSearch();
CustomRecordSearchBasic basicRecordSearchParts = new CustomRecordSearchBasic();
basicRecordSearchParts.recType = new RecordRef { internalId = "64" }; //"Order Item" NetSuite Type ID
//adding a search filter on a String Custom Field
SearchStringCustomField partTypeFieldSearch = new SearchStringCustomField();
partTypeFieldSearch.#operator = SearchStringFieldOperator.#is;
partTypeFieldSearch.internalId = "896"; //ID of the Part object's "Type" field
partTypeFieldSearch.operatorSpecified = true;
partTypeFieldSearch.searchValue = "Inventory Item"; //only want inventory item parts
//Show me only parts on a certain Order
CustomSearchJoin orderSearchJoin = new CustomSearchJoin();
CustomRecordSearchBasic orderBasicSearch = new CustomRecordSearchBasic();
orderBasicSearch.recType = new RecordRef { internalId = "56" }; //"Order" NetSuite Type ID
//-- WHAT GOES HERE INSTEAD OF SearchStringCustomField?
//adding a search filter on a String Custom Field
SearchStringCustomField fsoItemTypeSearch = new SearchStringCustomField();
fsoItemTypeSearch.#operator = SearchStringFieldOperator.#is;
fsoItemTypeSearch.internalId = "name"; //I have the "name" and numeric "internal id" of the order available.
fsoItemTypeSearch.operatorSpecified = true;
fsoItemTypeSearch.searchValue = order_name;//search filter value
orderSearchJoin.searchRecordBasic = orderBasicSearch;
//add in the things we want to search on
basicRecordSearchParts.customFieldList = new SearchCustomField[] { partTypeFieldSearch };
//add the basic search and join search and then perform the search
searchParts.basic = basicRecordSearchParts;
searchParts.customSearchJoin = new CustomSearchJoin[] { orderSearchJoin };
SearchResult response = netSuiteService.search(searchParts);
return response;
}

Getting the profileid for a userid

In our company we created a custom Issues app. Additionally to using this app in the web interface, we also want to be able to change the state of an issue (new, acknowledged, test, resolved, ...) automatically via git commit hooks. The basics are working fine (ie change state, add notes, ...), but we also want to change the responsibility for the current item to a specific user. In that special case, it's the creator if this item.
My first try was the following:
var appid = 1234; var itemid = 1;
var item = podio.ItemService.GetItemByAppItemId(appid, itemid);
var update = new Item {ItemId = item.ItemId};
var creator = item.CreatedBy.Id;
var resp = update.Field<ContactItemField>("responsibility");
resp.ContactIds = new List<int>{creator.Value};
//change some other fields as well
podio.ItemService.UpdateItem(update);
This throws an "Object not found" exception, because in the resp.ContactIds one must not set the UserId but the ProfileId.
I then tried to get the ProfileId of the item-creator via
podio.ContactService.GetUserContactField(creator.Value, "profile_id");
but this also throws an exception "(Authentication as app is not allowed for this method").
So how can I get an appropriate profile id for the user when I use authentication as app?
OK, I found a workaround for it, not sure, if this is possible for other scenarios, but it works for the current case.
Instead of using the C# interface for setting the ContactIds for the ContactItemField, I set the json values directly.
var appid = 1234; var itemid = 1;
var item = podio.ItemService.GetItemByAppItemId(appid, itemid);
var update = new Item {ItemId = item.ItemId};
var creator = item.CreatedBy.Id;
var resp = update.Field<ContactItemField>("responsibility");
resp.ContactIds = new List<int>(); // set to an empty list, so that resp.Values is initialized to an empty JArray
var u = new JObject { {"value", new JObject { {"type" , "user" }, {"id", creator } } } };
responsibleField.Values.Add(u); //add the new user to the Values of the field
//change some other fields as well
podio.ItemService.UpdateItem(update);
And if I set the value with type user I can use the known userid and the API on the server takes care of the lookup.

Error creating an Entity in CRM 2011 - CRM doesn't like OptionSetValue

I'm trying to create an entity in CRM 2011 (not an out of the box kind, but what in CRM 4 would have been called a DynamicEntity... one with my custom attributes). The code below gives me this error and I'm not sure why. This exact same code works if I remove the new_accounttype attribute and try to use another custom attribute.
CRM seems to have taken issue with the "OptionSetValue" being set as the value for that key value pair. new_accounttype is a picklist (or OptionSet in CRM 2011) and that value of 100000003 was pulled from the front end so it's a valid value.
Error: A validation error occurred. The value of 'new_accounttype' on
record of type 'account' is outside the valid range.
What am I doing wrong?
public static void CreateAccount(string accountName, string accountType)
{
//Create properties
KeyValuePairOfstringanyType[] attributes = new KeyValuePairOfstringanyType[2];
attributes[0] = new KeyValuePairOfstringanyType() { key = "name", value = accountName ?? "" };
attributes[1] = new KeyValuePairOfstringanyType() { key = "new_accounttype", value = new OptionSetValue() { Value = 100000003 } };
////Create DynamicEntity
Entity accountToCreate = new Entity();
accountToCreate.LogicalName = "account";
accountToCreate.Attributes = attributes;
try
{
service.Create(accountToCreate);
}
}
I agree that what you have should work fine. This can only mean that the value isn't published or is incorrect. As #glosrob mentions, check that the changes are actually published. Confirm these values by looking at the published form and seeing if your new value is present (and perhaps double check by using IE Developer Tools - hit F12 - and confirm that the value in the select>option object in the HTML contains the integer you expect).
As an aside, your code looks more complex than necessary (IMHO!). I believe this is easier to read an no less efficient:
Try this:
public static void CreateAccount(string accountName, string accountType)
{
////Create DynamicEntity
Entity accountToCreate = new Entity();
accountToCreate.LogicalName = "account";
accountToCreate.Attributes = attributes;
//Append properties
accountToCreate.Attributes.Add("name", accountName ?? "" );
accountToCreate.Attributes.Add("new_accounttype", new OptionSetValue(100000003);
try
{
service.Create(accountToCreate);
}
}
Give this a shot: key = "new_accounttype", value = new OptionSetValue(100000003)

Categories