Sitecore 8 Update 5 FieldChanges functionality during publish - c#

We are using Sitecore 8 update-5. We would like to check which values changed in a specific field during a publish. For this we are subscribed to the item:saved event handler. When extracting the ItemChanges parameter from the event arguments we use the FieldChanges property for that field. In the master database the FieldChanges dictionary contains only those fields that were changed and FieldChanges.OriginalValue and FieldChanges.Value contains the proper values (the old ones and the new ones). However when publishing from master to web DB it seems that the FieldChanges always contain all fields and the OriginalValue and Value properties are always the same. We tested this with items which were already existing in web database, using smart publish and a single language.
The question is this is how it should work or is this a bug?
Some example code:
var topicFieldID = new ID(RelatedTopic.FieldIDs.Topics); //getting the field ID
var changes = Event.ExtractParameter<ItemChanges>(args, 1); //in item:saved event handler
var oldIDs = changes.FieldChanges[topicFieldID]?.OriginalValue?.ToString().Split('|');
var newIDs = changes.FieldChanges[topicFieldID]?.Value?.ToString().Split('|');
and in our case the "oldIDs" and "newIDs" contain the same values in web DB
Regards,
Chris

Related

How to add Triggers to Transitions in Enterprise Architect using C#

Moving on from my previous problem, now I need to add Triggers to my transitions in State Machine diagram. How to acheive this using C#. The following creates a transition and its gaurd value but the trigger is not getting added.
EA.Connector trans = psosDiagramElement.Connectors.AddNew(tb1[i].Text, "StateFlow");
trans.ClientID = GetElementByName(txtSourceElement.Text);
trans.MetaType = "Transition";
trans.TransitionGuard = tb1[i].Text;
trans.SupplierID = GetElementByName(cmb1[i].SelectedItem.ToString());
trans.Direction = "Source -> Destination";
trans.Constraints.AddNew("A", "Signal");
trans.Update();
I don't think that there is a direct API call available to update the trigger.
TransitionEvent property of connetor will only update specification value.
Workaround for updating trigger is to hit a direct query using below call.
Repsitory.Execute(TriggerQuery)
You need to update\add a value in t_xref with
name as MOFProps
Type as connector property
Behaviour as trigger and
Description column you need to update the GUID value of triggers ( it will also accept Comma separated value as shown in diagram below )
Sample Insert query: Insert into t_xref (Name,Type,Visibility,Behavior,Description,Client) values ('MOFProps','connector property','public','trigger','triggereaguid1,triggereaguid2','connectorid');

Required field display name change issue

I'm currently doing a little bit of upgrading to a solution 3 upfates of which are display name changes.
I have 3 fields
A date field Approved - Required
A date field expiry - Required
Number - Not Required
I update these fields display names at site level and push the changes down.
The result is that all fields are updated at site level.
Only the Number field gets updated in the site content types.
I'm not getting anything back from the ULS logss, Is this a special feature of SharePoint that you can't update the display names of required fields programmatically?
private void UpdateFieldDisplayNameAndDescription(SPSite site, string fieldStaticName, string newFieldDisplayName, string description, bool isRequired)
{
try
{
using (SPWeb web = site.RootWeb)
{
SPField field = web.Fields.TryGetFieldByStaticName(fieldStaticName);
if (field != null)
{
field.Title = newFieldDisplayName;
if (!string.IsNullOrEmpty(description))
{
field.Description = description;
}
field.Required = isRequired; // Tried this method without this here also.
field.PushChangesToLists = true;
field.Update(true);
}
}
}
Any Ideas
My next step is to make sure that this is also replicated to any content types within lists but don't want to try that until this little niggle is sorted. Any ideas or tips?
I am running this under a custom action(feature upgrade)
I believe the reason for the push down not working for the two required fields is because the XML that defines them has been updated in the projects lifespan, The Number field that was updating correctly has never been changed.

How do I add a column into a data set loaded with an outdated schema in C#?

Background
Here is my issue. Earlier in the course of my program a System.Data.DataSet was serialized out to a file. Then sometime later the data set schema was changed in the program, specifically a column was added to one of the tables.
This data set has been created using VS and C#, so it has all the properties able to access the rows and columns by name (through the Microsoft generated code). It has all the files (.xsd, .cs, etc.) that VS needs to know what the data set looks like and the names therein.
The file is loaded and saved through XML Serialization. This causes an issue now because when I deserialize the old file it loads in the data related to the old schema. This works for the most part, but the object that is created (the data set) has everything but the column that was added later. So, when trying to access the new column it fails because the deserialization did not know about it and the entire column winds up being null.
This now causes more issues because it throws an exception when trying to access that column (because it's null) through the properties of the data set.
Question
My question is, can I somehow add in the column after deserialization? I apparently need to add it so that it complies with the Microsoft generated code because doing this:
myDataSet.myTable.Columns.Add("MyMissingColumn");
...does not add the column it needs. It may add a column, but the row property myDataRow.MyMissingColumn returns null and errors out.
Do I need to somehow copy the new schema into this object? Again, the only reason this is failing is because the old file was serialized using the old schema.
Any suggestions are appreciated.
Why don't you load the schema from the new schema file, and then load the old data. Provided your column allows nulls it should be fine.
DataSet data = new DataSet();
data.ReadXmlSchema(schemaFile);
data.ReadXml(dataFile, XmlReadMode.IgnoreSchema);
Otherwise just add it on the fly:
if (!data.Tables[0].Columns.Contains("SomeId"))
{
var column = new DataColumn("SomeId", typeof(int));
// give it a default value if you don't want null
column.DefaultValue = 1;
// should it support null values?
column.AllowDBNull = false;
data.Tables[0].Columns.Add(column);
}
you are adding a new column without specify its data type, strange, I would specify typeof(string) using another overload of the Add.
beside this, it's understandable that you cannot do: myDataRow.MyMissingColumn because there was no type/column mapping in the initial version of the XSD, but can you anyway access to this column by name or index?
try something like this
myDataRow["MyMissingColumn"] = "Test";
var s = myDataRow["MyMissingColumn"].ToString();

Loading a Null String and Silverlight 4

I maintain a Silverlight 4 application. While I was out of the office, the database structure was changed and a table was dropped and its fields combined into another existing table. Now, I’m receiving the following error after I create a new item and proceed to its "summary" screen:
“Value cannot be null. Parameter name: Text
At System.Windows.Controls.TextBox.set_Text(String value)”
This only happens with newly created entries, not older entries where the information on the next screen is complete (data was converted from an Excel spreadsheet and loaded into the database). So, I’ve narrowed it down this: the child window that is used to create a new record doesn’t have all the fields that were added to the table because some of the information isn’t available when the record is created. A Google search turned up that null strings can’t be passed in Silverlight.
The Summary screen is loaded via ddsSummaryLoadedData domain service. If I don’t include the “new” fields, then the values aren’t loaded for existing entries, but new entries don’t cause an error. If I do include them, older entries load correctly but new ones give the above error.
Is there a workaround to create the empty fields until they’re needed, but still load data if it exists (for older entries)? Or does the child window need to be redesigned? I’m new to Silverlight and still have so much to learn!
It doesn't look like you're using Bindings to render your view otherwise null values will be handled gracefully, so if you are setting the Text property manually in code, use the cascading operator to verify you are not submitting a null value.
myTextBox.Text = myModelValue.FirstName ?? string.Empty;

ASP.NET Dynamic form generation and submition

I need to create a form where for each day in the month the user will enter in several different values (Im thinking a grid sort of thing, values along the top, day of the month along the side) using ASP.NET forms with C# backend...
So what would be the best way to generate this form? I dont want to hardcode that many controls as it would make the submition a little annoying but i also would need to be able to give it values entered in previous days and have it display them in the textboxes.
How would i go about creating this form and also how would i get the values from the textboxes in the backend?
Here is an example application that creates a dynamic form and submits it back to the database. It's written in VB.Net but im sure it's easily converted to C#.
http://www.asp101.com/samples/form_dynamic_aspx.asp
Basically the way it works is adding the controls to the form dynamically then accessing the values that are posted to the server with the Request.Form collection.
If you're building from scratch and can use the ASP.NET MVC framework, might be worth checking out the Dynamic Forms project over at codeplex: http://mvcdynamicforms.codeplex.com/
It might be overkill for your situation, but this appears a pretty powerful way to have a dynamic forms approach (you can store the config in an XML file, in a database etc), and posting the data back is handled by evaluating the Request object in server side code.
You can do this very easily using my FormFactory library.
By default it reflects against a view model to produce a PropertyVm[] array:
```
var vm = new MyFormViewModel
{
OperatingSystem = "IOS",
OperatingSystem_choices = new[]{"IOS", "Android",};
};
Html.PropertiesFor(vm).Render(Html);
```
but you can also create the properties programatically, so you could load settings from a database then create PropertyVm.
This is a snippet from a Linqpad script.
```
//import-package FormFactory
//import-package FormFactory.RazorGenerator
void Main()
{
var properties = new[]{
new PropertyVm(typeof(string), "username"){
DisplayName = "Username",
NotOptional = true,
},
new PropertyVm(typeof(string), "password"){
DisplayName = "Password",
NotOptional = true,
GetCustomAttributes = () => new object[]{ new DataTypeAttribute(DataType.Password) }
}
};
var html = FormFactory.RazorEngine.PropertyRenderExtension.Render(properties, new FormFactory.RazorEngine.RazorTemplateHtmlHelper());
Util.RawHtml(html.ToEncodedString()).Dump(); //Renders html for a username and password field.
}
```
Theres a demo site with examples of the various features you can set up (e.g. nested collections, autocomplete, datepickers etc.)

Categories

Resources