Sitecore Field Id's vs Field Name's - c#

I read it in "Professional Sitecore Development" book by - John West saying that it's best practice to use Field ID's instead of Field names while getting the Item Field value.
But sitecore Controls like sc:text, sc:link, sc:image etc have an attribute called field which uses field name. So, i am confused now whether to change the whole project to Field ID's or leave it with field names to be consistent with sitecore usage.
Any suggestions will be appreciated.

Yes, Sitecore allows you to use Names and IDs. Also Sitecore allows you to have identical fields names in a same template, what may cause some confusion. IDs, of course, can not be duplicated.
I believe it is more reliable to use IDs instead of names. Names can easily be changed on Sitecore, and it is hard to find the error when that happens. You won't get compilation error or anything like that until someone notice the field value is not there.
A good approach is to use a code generator (like T4 or TDS) to create strongly typed classes to be used in your code. Something like:
public static struct MyTemplate
{
public static struct MyGroup1
{
public static readonly ID Foo = new ID("{1111111-1111-1231-1231-12312323132}");
}
public static struct MyGroup2
{
public static readonly ID Foo = new ID("{9999999-9999-xxxx-1231-12312323132}");
}
}
Then you go that way on your controls:
#Html.Sitecore().Field(MyTemplate.MyGroup.Foo); //where foo returns the id.
Hope that helps..

As an FYI adding to #RobertoBr's excellent answer, Sitecore uses GUIDs internally to access well known fields. If you decompile Sitecore.Kernel.dll and look in the static class Sitecore.FieldIDs you will see a list of fields you would be very familiar with using, e.g.
public static ID Created = new ID("{25BED78C-4957-4165-998A-CA1B52F67497}");
public static ID CreatedBy = new ID("{5DD74568-4D4B-44C1-B513-0AF5F4CDA34F}");
public static ID DisplayName = new ID("{B5E02AD9-D56F-4C41-A065-A133DB87BDEB}");
Very similar to what RobertoBr has suggested.

I would recommend you to use field IDs instead of field names in all cases.
Field IDs usage prevents a lot potential mistakes, misspell, etc..
You don't need to worry about correct behavior if you will decide to rename some fields (or other developer will decide to rename his fields).
If you use template's inheritance, you may have potential bugs with duplicates of field names.
Field IDs usage prevents unnecessary processing. Because when you are using field name, Sitecore resolves field ID by field name and after that retrieves field by ID.

Related

Get property private member name

So I have this.
private int _SomeDataBaseField_;
public int ID
{
get { return _SomeDataBaseField_; }
set { _SomeDataBaseField_ = value; }
}
What I am trying to do is map the property name and the private field name in a way that I can pull the private field name using the property name only and without using any attributes or tags.
So my question is:
Is there any way to deduce the private field name using only the property name? Something like
string PrivateFieldName = typeof(T).GetProperty("ID").GetPrivateFieldName();
Where PrivateFieldName would be SomeDataBaseField.
I tried to use reflection but no luck.. This is as far as I got and it only shows the private field type (Int32) which is not very helpful.
foreach (PropertyInfo item in typeof(T).GetProperties())
{
LocalVariableInfo lv = item.GetAccessors()[0].GetMethodBody().LocalVariables[0];
}
Edit:
I feel I need to explain why I need this.
So I have a class that contains 1200+ properties and they all have private fields (backing fields). now I already spent countless hours creating the mysql database table for that class and now that I am using it I realized that I am going to have to manually type the field name every time I need to update one of the fields in the database. So I thought I would use the private field name as a database column and then supply the update function with the property name which would then look up some collection of <'PropertName, PrivateName'> for the corresponding private field name and use that as the database field name. This would not only save time but it would also limit the need for typing the field names over and over again whenever they need to be updated or parsed.
Thanks in advance.
Use typeof(T).GetFields instead.
A Property in C# is a logical grouping of two CLR Methods (a getter and a setter). A property does not necessarily have a single backing field - it doesn't have to have any, or it could have multiple. You shouldn't make that assumption.
Not every property is backed by a single field - all variants 0-infinity are possible, so you need to review what your goals are.
Proper way would be to parse IL of each property get/set pair and find what (if any) packing field their are using. Such approach would let you detect non-trivial properties that use more than one backing field (or none at all). GetMethodBody is starting point for such code - some info can be found in Can I use reflection to inspect the code in a method?
More practical way would be to rely on some sort of convention to find matches.
I.e. for auto-properties compiler generates predictable names (implementation-dependent) and you can find matching field as shown in Is it possible to access backing fields behind auto-implemented properties?.
For other cases there is usually some naming convention - i.e. field with same name but different case/prefix/suffix. Basic string matching would help for such cases.

Sitecore - How do I correctly populate the Item.Fields hashtable with names for the key (not GUIDs)?

This is a bit of a strange one with Sitecore... Basically I'm accessing an item from the Content API but it's not populating the Item.Fields hashtable with keys based on the text for the field (I guess I'd call this a field name) but rather with a GUID.
For example, here is some code I'm using to get an item:
var database = global::Sitecore.Configuration.Factory.GetDatabase("master");
var item = database.GetItem("/sitecore/content/Home");
item.Fields.ReadAll(); // edit, per recommendation... does not work
Sitecore.Data.Fields.Field f = item.Fields["SomeText"];
Assert.IsNotNull(f): // This fails
If I set a breakpoint and debug, I can see that there are values (indeed, the correct values) inside the Item.Fields hashtable, but the keys are all based on GUIDs rather than "field names" as most code samples regarding usage of this API suggest.
EDIT: Upon closer inspection, the DisplayName and Name fields are coming back as empty strings from the API (note these are clearly defined in Sitecore so still not sure what the issue is). It appears these might be used in conjunction with GUID as some sort of key for the hashtable.
Question: Is there something I'm doing wrong here? I've published the data template and the content item. Clearly the connection is being made because I'm getting results back from the API and even the correct values, just not the keys I'm expecting to use to reference the data values.
References:
http://sdn.sitecore.net/upload/sitecore6/content_api_cookbook-a4.pdf - checkout the example right at the top of page 28 where they access the "title" field. Also, check out the example directly below in 4.1.1 "How to Access System Fields" where they use static helpers with the GUIDs instantiated in a private static constructor. Is this the preferred method for accessing "user defined" fields?
Screenshot of sample data from Sitecore (notices the GUIDs as keys):
Code Samples from above linked document:
Accessing the "title" field:
Sitecore.Data.Database master = Sitecore.Configuration.Factory.GetDatabase("master");
Sitecore.Data.Items.Item home = master.GetItem("/sitecore/content/home");
Sitecore.Data.Fields.Field titleField = home.Fields["title"];
if(titleField!=null)
{
home.Editing.BeginEdit();
titleField.Value = "//TODO: replace with appropriate value";
home.Editing.EndEdit();
}
Accessing the system field "ArchiveDate":
Sitecore.Data.Database master = Sitecore.Configuration.Factory.GetDatabase("master");
Sitecore.Data.Items.Item sample = master.GetItem("/sitecore/content/home/sample");
Sitecore.Data.Fields.DateField archiveField =
sample.Fields[Sitecore.FieldIDs.ArchiveDate];
Decompiling the Sitecore.Kernel.dll we can see that:
public static class FieldIDs
{
// stripped down version
/// <summary>The ID of the 'Archive date' field.</summary>
public static ID ArchiveDate;
static FieldIDs()
{
FieldIDs.ArchiveDate = new ID("{56C15C6D-FD5A-40CA-BB37-64CEEC6A9BD5}");
}
}
If I understand correctly, you want the Fields collection to return all the fields available for that item, even if they do not have a value. By default, Sitecore will only return those fields that have a value.
You can solve this by calling the ReadAll() method before accessing the fields collection.
So in your example:
item.Fields.ReadAll();
Sitecore.Data.Fields.Field f = item.Fields["SomeText"];
Assert.IsNotNull(f): // This succeeds
I had a problem with identical symptoms. The root cause for me was a publishing issue. The folder containing my template was not published, though the template itself was. So I could see the fields in the debugger with the correct values and ids, but not the names. The solution was to ensure that all the parents of my template were also published.
So, I ended up going the route I mentioned in the question (which is what Sitecore uses internally and, #technophoria414 mentioned, a Sitecore developer best practice).
Basically:
namespace MyProject.Core.Data.Sitecore.Fields
{
public static class ContentItem
{
// stripped down version
public static ID DESCRIPTION_TEXT;
static ContentItem()
{
DESCRIPTION_TEXT= new ID("{56C15C6D-FD5A-40CA-BB37-64CEEC6A9BD5}"); // this will be some GUID out of Sitecore
}
}
}
Usage would be something like this:
var query = string.Format("fast:/sitecore/content/HomePageItems//*[#ContentSlug='{0}']", input);
var item = Database.SelectSingleItem(query);
var descriptionText = item.Fields[ContentItem.DESCRIPTION_TEXT].Value;

I am using reflection to get property names and values in ASP.NET need some advice on optimization

I am using reflection to get property (as in {get; set} properties) names and their value. I would like to optimize this reflection. I don't have access to the code of the client classes I am using the reflection on, but after figuring out the property names of the class involved I will be reusing the same properties again and again.
I am doing this in an ASP.NET application and so I was thinking of storing some cached results in the Application (HttpContext.Current.Application) so the first user would have the primary increased performance load, but as requests scale other users can use the cached results of the first user.
NHibernate
Marc Gravell's HyperDescripter
Can somone give me a very laymans explanation of if Marc Gravel's solution is appropriate here, or if something like NHibernate is good for this situation? Or should I just cache the results of aquiring the property names in the class via reflection in a list and then use that when I need to enumerate property names?
HyperDescriptor is designed for the specific purpose of fitting inside the ComponentModel API. If you don't use that, it may be overkill. Just caching the data inside a static generic type can be pretty effective, using a static constructor to populate the data. By which I mean: store the data per-T:
public static class PropertyCache<T>
{
public static SomeType SomeName { get { return someField; } }
static PropertyCache() {
// init someField
}
}
...
var foo = PropertyCache<Foo>.SomeName;
You answered yourself.
"Or should I just cache the results of aquiring the property names in the class via reflection in a list and then use that when I need to enumerate property names?"
I implemented this using a hashtable.
Check this: https://stackoverflow.com/a/8038933/497982

How to create immutable objects in C#?

In a question about Best practices for C# pattern validation, the highest voted answer
says:
I tend to perform all of my validation in the constructor. This is a must because I almost always create immutable objects.
How exactly do you create an immutable object in C#? Do you just use the readonly keyword?
How exactly would this work if you want to validate in the constructor of your Entity Framework generated model class?
Would it look like below?
public partial readonly Person
{
public Person()
}
The interesting question here is your question from the comments:
What kind of object would you have that you do not need to modify the values at some point? I'm guessing not a model class, correct? I've had to change the name of a person in my database - this wouldn't fit with this idea.
Well, consider things that are already immutable. Numbers are immutable. Once you have the number 12, it's 12. You can't change it. If you have a variable that contains 12, you can change the contents of the variable to 13, but you are changing the variable, not the number 12.
Same with strings. "abc" is "abc", and it never changes. If you have a variable that contains "abc", you can change it to "abcd", but that doesn't change "abc", that changes the variable.
What about a list? {12, "abc"} is the list that is 12 followed by "abc", and that list never changes. The list {12, "abcd"} is a different list.
And that's where things go off the rails. Because in C# you can do it either way. You can say that there is referential identity between those two lists if lists are allowed to mutate their contents without changing their identity.
You hit the nail right on the head when you talk about the "model". Are you modeling something that changes? If so, then it is possibly wise to model it with a type that changes. The benefit of that is that the characteristics of the model match the system being modeled. The down side is that it becomes very tricky to do something like a "rollback" functionality, where you "undo" a change.
That is, if you mutate {12, "abc"} to {12, "abcd"} and then want to roll back the mutation, how do you do it? If the list is immutable you just keep around both values and choose which one you want to be the "current" value. If the list is mutable then you have to have the undo logic keep around an "undo function" which knows how to undo the mutation.
As for your specific example, you certainly can create an immutable database. How do you change the name of someone in your immutable database? You don't. You create a new database that has the data you want in it. The trick with immutable types is to do so efficiently, without copying billions of bytes. Immutable data structure design requires finding clever ways to share state between two nearly-identical structures.
Declaring all fields readonly is a good step towards creating an immutable object, but this alone is not sufficient. This is because a readonly field can still be a reference to a mutable object.
In C# immutability is not enforced by the compiler. You just have to be careful.
This question has two aspects:
Immutable type when you instantiate object
Immutable type when EF instantiate object
The first aspect demands sturcture like this:
public class MyClass
{
private readonly string _myString;
public string MyString
{
get
{
return _myString;
}
}
public MyClass(string myString)
{
// do some validation here
_myString = myString;
}
}
Now the problem - EF. EF requires parameterless constructor and EF must have setters on properties. I asked very similar question here.
Your type must look like:
public class MyClass
{
private string _myString;
public string MyString
{
get
{
return _myString;
}
private set
{
_myString = value;
}
}
public MyClass(string myString)
{
// do some validation here
_myString = myString;
}
// Not sure if you can change accessibility of constructor - I can try it later
public MyClass()
{}
}
You must also inform EF about private setter of MyString property - this is configured in properties of enitity in EDMX file. Obviously there will be no validation when EF will materialize objects from DB. Also you will not be able to use methods like ObjectContext.CreateObject (you will not be able to fill the object).
Entity Object T4 template and default code generation create factory method CreateMyClass instead of constructor with paremeters. POCO T4 template doesn't generate factory method.
I didn't try this with EF Code first.
An immutable value object is a value object that cannot be changed. You cannot modify its state, you have to create new ones
Check out Eric Lippert's blog:
Kinds of Immutability
https://learn.microsoft.com/en-us/archive/blogs/ericlippert/immutability-in-c-part-one-kinds-of-immutability
Have a look at
Immutable object pattern in C# - what do you think?
How exactly would this work if you want to validate in the constructor of your Entity Framework generated model class?
It wouldn't work in this context because EF requires the properties of the entity class be public otherwise it can't instantiate it.
But you're welcome to use immutable objects further in your code.
C# 9 is coming up with new feature names as Record. Init-only properties are great if you want to make individual properties immutable. If you want the whole object to be immutable and behave like a value, then you should consider declaring it as a record:
public data class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
}
The data keyword on the class declaration marks it as a record.
Reference: https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/#records
#Eric Lippert Good comment, but in addition in answer to the question:
What kind of object would you have that you do not need to modify the
values at some point? I'm guessing not a model class, correct? I've
had to change the name of a person in my database - this wouldn't fit
with this idea.
Let's say you have a large datastructure and you want to query its information, but it's changing all the time. You need some kind of locking system to make sure that you don't say try and count the total in the system while somebody is depositing something from one place to another. (Say a warehouse management system)
And that's hard to do because these things always affect things in unexpected ways, the data changing under your feet.
What if you could freeze your large datastructure when you're not updating it, so that no memory can be altered and it is paused at a consistent state? Now when you want to change it again you have to copy the datastructure to a new place, and it's fairly large, so that's a downside, but the upside is you won't have to lock anything because the new copy of the data goes unshared until it has been updated. This means anyone at any point can read the latest copy of the datastructure, doing complex things.
So yep very useful concept if you hate dealing with concurrency issues and don't have too much data to deal with. (E.g. if 1MB of data and updating 10/sec that's 10MB of data being copied)

Problem in selecting constants of an enum class

I've encourted a problem recently about cycling between constants of an enum class in .net (that is created from my OWL class, by Rowlex OwlGrinder). Problem was solved by means of using .net reflection (thanks to great help from dear Mr. Jon Skeet):
stackoverflow:problem-cycling-enum-class-values
By solving this, I started using it. After matching a dropDownList selected value to one of the enum class instances, I had to declare the selected object(=Language) to my RDF subject(=learningResource), via a predicate (=hasLanguage).
//learningResource is a new RDF subject, hasLanguage is predicate, and there
//is a new value for it - Language.
System.Reflection.FieldInfo[] resLanFields =
typeof(Language).GetFields();
for (int i = 0; i < resLangFields.Length; i++)
{
if (resLanFields[i].Name.Equals(dropDownList_lang.SelectedValue))
learningResource.hasLanguage = ??? //i-th constant of Language
}
Now the problem appears; I can not use Language[i] (or something like this to select i-th constant of Language class) to assign to hasLanguage. Is there a way to select i-th constant of an enum class (like refelections)?
Would any one please help me in this situation?
The Language class is not an enum in C# terminology. It is an ordinary class with public const string fields. ROWLEX intentionally generates enum-imitating-classes instead of native enums for 2 reasons:
The value of an native C# enum is an integer, while a public const string field can take the URI of the OWL class instance.
The class can have one additional public static string that is "URI" which represents the class URI consistently for every single ROWLEX generated class.
That was the background. If I understood your question right, you had an issue binding the selected name displayed in the dropdown back to the URI, and you wanted to use the position of the element inside the array you created. I would not do it that way. DropDownLists typically have both ID and Value fields for every list item (can be named differently component to component). The ID is expected to be a unique object while the Value is expected to contain something human readable. Set the ID with URI of the "enum" field, and the Value as you have done. So this is how you populate your dropdown:
System.Reflection.FieldInfo[] resLanFields = typeof(Language).GetFields();
foreach(FieldInfo field in resLanFields)
{
ListItem item = new ListItem();
item.ID = field.GetValue(null); // takes the URI value of the const field
item.Value = field.Name; // takes the name of the const field
dropDownList_lang.AddItem(item);
}
And when the user made his/her choice, this is how you read the result out:
learningResource.hasLanguage = (string) dropDownList_lang.SelectedItem.ID;
Since there is implicit casting operator implemented on the ROWLEX enum-imitating-class (string=>Language) you can safely set your triple subject as a string. Should compile without issue. Simple, isn't it?
;)
I'd say
resLanFields[i].GetValue(null)
but if this works, don't vote me up, this was in Jon's original answer.

Categories