More in this section

Forums / Developing with Sitefinity / New Data/Tables

New Data/Tables

11 posts, 0 answered
  1. Randel
    Randel avatar
    50 posts
    Registered:
    30 Aug 2012
    12 Sep 2008
    Link to this post
    Ok, I've looked at setting multiple Categories to an Event, News, Blog, etc...  I also know this feature is completed, just not rolled out.  Don't get me wrong, I believe this is a huge issue and I will definately use it heavily once it's availible.  However, I was just rethinking how I wanted to solve my problem.

    Site/Projects:
    - I have multiple Sitefinity sites/projects that use a shared database, "Public.xxx.com", "Student.xxx.com", "Instructor.xxx.com", etc...

    Original Solution:
    - Create a control, using a CheckListBox, which displays all "base" categories and which allows for multiple categories to be selected, and so on and so on and so on....

    New Thought/Solution:
    - Add a completely new table, called "Sites", and maybe even a junction table in which to place my many-to-many data.  My thought would is to extend Sitefinity to all my to filter on this new data.  What kind of thoughts or help can I get from the Sitefinity Team?

  2. Ivan
    Ivan avatar
    478 posts
    Registered:
    16 Jun 2015
    16 Sep 2008
    Link to this post
    Hello Randel,

    first of all I am afraid that there was a misunderstanding. We have not implemented the ability to have hierarchical categories or multiple categories per item - and they will not be rolled out with the next release. We are going to improve the way categories and tags work in the next major release - Sitefinity 4.0, but that is not the next release. There will be at least one release prior to 4.0.

    As for the second part of your post, I think that junction table with many-to-many relationship would be the most solid solution. If implemented properly you could have your solution for a long time, even once we roll out our new version of categories.

    I hope you'll find this information helpful. Let us know if there is anything else we can do for you.

    Kind regards,
    Ivan
    the Telerik team

    Check out Telerik Trainer, the state of the art learning tool for Telerik products.
  3. Randel
    Randel avatar
    50 posts
    Registered:
    30 Aug 2012
    16 Sep 2008
    Link to this post
    Ivan,

    I'm sorry, but I'm very disappointed in the help given for this thread.  Yes, you did clear up my misunderstanding of the multiple Categories per Event, News, Blog, etc...

    And I don't me to sound ungrateful or arrogant, and maybe I should have just asked for the technical help I needed.  But telling me "... If implemented properly ... " and not giving me any pointers or direction to implement it properly doesn't help me, does it?

    So let me try this again. 
    1) What help or example can I get to add a new property, one in which I'll be filtering and sorting on, to Events. 

    2) What pointers can I get with using Nolics.NET?
  4. Randel
    Randel avatar
    50 posts
    Registered:
    30 Aug 2012
    18 Sep 2008
    Link to this post
    Is there anyone out there that can help me add a property to the Events module?  My goal is to have a CheckListBox and assign the selected values to the event.  Then, when I want to display these events in different pages or different sites (I'm using a shared database), I can then filter out what I want to display.  Again, since my intention is to use a CheckListBox, the filter value may contain one or more items.

    Any ideas and/or pointers will be greatly appreciated.
  5. Gabe Sumner
    Gabe Sumner avatar
    440 posts
    Registered:
    09 Sep 2007
    19 Sep 2008
    Link to this post
    Hi Randel,

    As I understand it; you have events you're sharing between 3 Sitefinity web sites via a shared database.  You want to add events and select which web site(s) the event displays on.

    My initial thought was to apply tags instead of categories to your events.  You could apply multiple tags to your events (Public, Student, Instructor) and filter accordingly:

    http://www.sitefinity.com/help/developer-manual/content-items-get.html#GetContent_by_from_max_sortExp_tagName

    I'm not sure how this might work in a shared database/multi-web site scenario however.  It might be worth investigating though.

    Your idea of creating a "Sites" table would also work.  However, I doubt you'll be able to use the existing Sitefinity Events module with this table.  Rather you would need to create your own custom Events Module. 

    In this scenario you could base your module off Generic Content or start from scratch & handle everything (including data access) with your own custom code.  Information about how to create a Sitefinity Custom Module can be found here:

    http://www.sitefinity.com/help/developer-manual/adding-new-modules-overview.html

    Regarding using Nolics in your custom module, my personal advice is to avoid it.  Certainly don't use it to directly alter the Sitefinity tables.  (Use the Sitefinity API to access Sitefinity data).  I also wouldn't recommend using Nolics for your own custom data tables.. 

    Sitefinity will work just fine along side other methods of data access.  Use whatever method you're comfortable with.  I've used LINQ to SQL in the past.  Other methods should work as well.  Just keep all your data in your own custom tables and don't touch the Sitefinity tables.  :)

    Gabe Sumner
  6. Bob
    Bob avatar
    330 posts
    Registered:
    30 Dec 2016
    19 Sep 2008
    Link to this post
    Hello Randel,

    I completely agree with Gabe but I just want to add some ideas that you may find helpful.

    Adding property of collection type is quite challenging. There are a couple of approaches you can try though. Unfortunately none of them is easy to implement and which one to choose really depends on how you want to use this property and how much effort you want to spend on this task.

    The most flexible approach is to override the data classes and the data provider. Nolics allows true inheritance and extending the event class with additional property will be relatively easy. However, you will have to override a lot of data provider methods in order to make this work and some of them are quite complex. I will have to write a whole chapter and a lot of sample code to explain this. Obviously that will take considerable time which doesn’t seem to be justified considering that we are going to move away from Nolics. With version 4.0 we are going to introduce new data access layer that will be much more flexible and easy to use for this kind of things.

    Maybe an easier way to go is to use loosely coupled approach.

    Here is an idea:
    1. Create the following file ~/App_Code/Extensions.cs
    2. Add the following code in that file
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
    using Telerik.Cms.Engine;  
     
    public static class Extensions  
    {  
        public static string[] GetCategories(this IContent content)  
        {  
            string[] categories;  
            if (eventsTable.TryGetValue(content.ID, out categories))  
                return categories;  
            return new string[0];  
        }  
     
        public static void SetCategories(this IContent content, params string[] categories)  
        {  
            if (categories != null && categories.Length > 0)  
                eventsTable[content.ID] = categories;  
            else if (eventsTable.ContainsKey(content.ID))  
                eventsTable.Remove(content.ID);  
        }  
     
        //Lets pretend we retrieve categories form database  
        public static string[] CustomCategories = new string[] { "Cat 1""Cat 2""Cat 3""Cat 4""Cat 5""Cat 6" };  
        //Lets pretend this is our events table in the database  
        private static Dictionary<Guid, string[]> eventsTable = new Dictionary<Guid, string[]>();  
    }  
     

    3. Create a User Control: ~/UserControls/CategoriesTest.ascx
    4. Place this declarations in the .ascx file
    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="CategoriesTest.ascx.cs" Inherits="UserControls_CategoriesTest" %> 
    <asp:CheckBoxList ID="MyCategories" runat="server"></asp:CheckBoxList> 

    5. Place this code in the code behind file
     
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
    using System.Web.UI;  
    using System.Web.UI.WebControls;  
    using Telerik.Cms.Web.UI;  
    using Telerik.Cms.Engine;  
    using Telerik.Cms.Engine.WebControls.Admin;  
     
    public partial class UserControls_CategoriesTest : System.Web.UI.UserControl  
    {  
        protected void Page_Load(object sender, EventArgs e)  
        {  
            ControlPanel.EditorContainer container = null;  
            Control control = this.NamingContainer;  
            while (control != null)  
            {  
                if (control is ControlPanel.EditorContainer)  
                {  
                    container = (ControlPanel.EditorContainer)control;  
                    break;  
                }  
                control = control.NamingContainer;  
            }  
            if (container != null)  
            {  
                this.eventItem = container.MetaFields.Content;  
                if (eventItem != null)  
                {  
                    this.MyCategories.Items.Clear();  
                    List<string> itemCategories = new List<string>(eventItem.GetCategories());  
                    foreach (string category in Extensions.CustomCategories)  
                    {  
                        ListItem listItem = new ListItem(category);  
                        listItem.Selected = itemCategories.Contains(category);  
                        this.MyCategories.Items.Add(listItem);  
                    }  
                    container.SaveButton1.Command += new CommandEventHandler(SaveButton_Command);  
                    //SaveButton2 is optional so we have to check if it is present  
                    if (container.SaveButton2 != null)  
                        container.SaveButton2.Command += new CommandEventHandler(SaveButton_Command);  
                }  
                else 
                {  
                    this.MyCategories.DataSource = Extensions.CustomCategories;  
                    this.MyCategories.DataBind();  
                }  
            }  
        }  
     
        void SaveButton_Command(object sender, CommandEventArgs e)  
        {  
            List<string> selectedCategories = new List<string>();  
            foreach (ListItem itm in this.MyCategories.Items)  
                if (itm.Selected)  
                    selectedCategories.Add(itm.Text);  
            this.eventItem.SetCategories(selectedCategories.ToArray());  
        }  
     
        private IContent eventItem;  
    }  
     

    6. Open ~/Sitefinity/Admin/ControlTemplates/Events/ControlPanelEdit.ascx
    7. Place this declaration on top
    <%@ Register TagPrefix="uc1" TagName="CategoriesTest" Src="~/UserControls/CategoriesTest.ascx" %> 

    8. Place the following declaration where you find appropriate in the template
    <uc1:CategoriesTest runat="server" /> 

    9. Run the project and see if you are able to set different categories for different items

    Note that the above code is valid for C# 3.0 and above.

    You can use similar control to display the categories in View mode in ControlPanel and EventsView controls.
     
    You must be aware that there is no efficient way to filter and sort by these custom categories. You have to do it either in memory, which means you have to retrieve all data, or you can query many-to-many table and then retrieve some limited number of items by ID. If you are displaying 10 - 20 items per page it shouldn’t be a problem.


    Sincerely yours,
    Bob
    the Telerik team

    Check out Telerik Trainer, the state of the art learning tool for Telerik products.
  7. Randel
    Randel avatar
    50 posts
    Registered:
    30 Aug 2012
    19 Sep 2008
    Link to this post
    Gabe, Bob:

    Thank you both for the great information.  If you cannot tell, I'm still very new to Sitefinity.  The fact that my company is still in the POC stage and still defining what belongs to a specific site and/or is sharable, doesn't help either.  So basically, I'm ask to do everything under the sun.

    I'll look at both your comments and see where it takes me.  Again, thank you both for the help.
  8. Randel
    Randel avatar
    50 posts
    Registered:
    30 Aug 2012
    22 Sep 2008
    Link to this post
    Hey Bob,

    I think I've done what you've ask/told me to do, but I get the following error:

    Meta field control must implement at least ITextControl.

    Server Error in '/Public.KyukiDo' Application.

    Meta field control must implement at least ITextControl.

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.InvalidCastException: Meta field control must implement at least ITextControl.

    Source Error:

    An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

    Stack Trace:

    [InvalidCastException: Meta field control must implement at least ITextControl.]
       Telerik.Cms.Engine.WebControls.ContentMetaFields.SetTextControl(Control ctrl, Object data) +88
       Telerik.Cms.Engine.WebControls.ContentMetaFields.CreateChildControls() +1433
       System.Web.UI.Control.EnsureChildControls() +87
       Telerik.Cms.Engine.WebControls.Admin.EditorContainer.LoadOptionalControls() +530
       Telerik.Cms.Engine.WebControls.Admin.ControlPanel.SetEditContainer(Int32 idx, StagedContent stg) +100
       Telerik.Cms.Engine.WebControls.Admin.ControlPanel.CreateEditView() +373
       Telerik.Cms.Engine.WebControls.Admin.ControlPanel.CreateChildControls() +1085
       Telerik.Events.WebControls.Admin.ControlPanel.CreateEventsContentView() +32
       Telerik.Events.WebControls.Admin.ControlPanel.CreateChildControls() +243
       System.Web.UI.Control.EnsureChildControls() +87
       System.Web.UI.WebControls.CompositeControl.RecreateChildControls() +21
       Telerik.Cms.Engine.WebControls.Admin.ControlPanel.set_Mode(Modes value) +823
       Telerik.Cms.Engine.WebControls.Admin.ControlPanel.Grid_RowCommand(Object sender, GridViewCommandEventArgs e) +221
       System.Web.UI.WebControls.GridView.OnRowCommand(GridViewCommandEventArgs e) +105
       System.Web.UI.WebControls.GridView.HandleEvent(EventArgs e, Boolean causesValidation, String validationGroup) +76
       System.Web.UI.WebControls.GridView.RaisePostBackEvent(String eventArgument) +199
       System.Web.UI.WebControls.GridView.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +7
       System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +11
       System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +177
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1746
    


    Version Information: Microsoft .NET Framework Version:2.0.50727.1433; ASP.NET Version:2.0.50727.1433



    So then I added "ITextControl" to the class definition and got this error:

    Unable to cast object of type 'ASP.usercontrols_emarketing_categoriestest_ascx' to type 'Telerik.Cms.Engine.WebControls.Categories.CategoriesField'.

    Server Error in '/Public.KyukiDo' Application.

    Unable to cast object of type 'ASP.usercontrols_emarketing_categoriestest_ascx' to type 'Telerik.Cms.Engine.WebControls.Categories.CategoriesField'.

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.InvalidCastException: Unable to cast object of type 'ASP.usercontrols_emarketing_categoriestest_ascx' to type 'Telerik.Cms.Engine.WebControls.Categories.CategoriesField'.

    Source Error:

    An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

    Stack Trace:

    [InvalidCastException: Unable to cast object of type 'ASP.usercontrols_emarketing_categoriestest_ascx' to type 'Telerik.Cms.Engine.WebControls.Categories.CategoriesField'.]
       Telerik.Cms.Engine.WebControls.Admin.EditorContainer.LoadOptionalControls() +591
       Telerik.Cms.Engine.WebControls.Admin.ControlPanel.SetEditContainer(Int32 idx, StagedContent stg) +100
       Telerik.Cms.Engine.WebControls.Admin.ControlPanel.CreateEditView() +373
       Telerik.Cms.Engine.WebControls.Admin.ControlPanel.CreateChildControls() +1085
       Telerik.Events.WebControls.Admin.ControlPanel.CreateEventsContentView() +32
       Telerik.Events.WebControls.Admin.ControlPanel.CreateChildControls() +243
       System.Web.UI.Control.EnsureChildControls() +87
       System.Web.UI.WebControls.CompositeControl.RecreateChildControls() +21
       Telerik.Cms.Engine.WebControls.Admin.ControlPanel.set_Mode(Modes value) +823
       Telerik.Cms.Engine.WebControls.Admin.ControlPanel.Grid_RowCommand(Object sender, GridViewCommandEventArgs e) +221
       System.Web.UI.WebControls.GridView.OnRowCommand(GridViewCommandEventArgs e) +105
       System.Web.UI.WebControls.GridView.HandleEvent(EventArgs e, Boolean causesValidation, String validationGroup) +76
       System.Web.UI.WebControls.GridView.RaisePostBackEvent(String eventArgument) +199
       System.Web.UI.WebControls.GridView.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +7
       System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +11
       System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +177
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1746
    


    Version Information: Microsoft .NET Framework Version:2.0.50727.1433; ASP.NET Version:2.0.50727.1433


    Do you have any suggestions as to what I'm doing wrong?
  9. Randel
    Randel avatar
    50 posts
    Registered:
    30 Aug 2012
    22 Sep 2008
    Link to this post
    Hey Gabe,

    What do you think about simply extending the current Event module using inheritance to create my own?
  10. Gabe Sumner
    Gabe Sumner avatar
    440 posts
    Registered:
    09 Sep 2007
    23 Sep 2008
    Link to this post

    Hi Randel,

    I would listen to Bob & Ivan far more than me.  Those guys are the masters.   :)

    Your idea of inheriting & extending the Events module is a creative solution and probably worth experimenting with.  I have no direct experience with this,  so I'm not the best person to give you advice.  My guess is this will get really complex & messy as you get deeper into the solution.

    If this was my project, and this was an essential feature, I would probably end up creating my own custom Events module... from scratch.  Everything would then be under my control.  I worry too much when I start overriding methods & events or toying with someone else's data access methods. 

    Due to the work involved, I would probably try to get everyone to be happy with a compromise before going down this path though.  For example, let's assume: 

    Instructors can view Instructor, Student & Public events.
    Students can view Student & Public events.
    Public can only view Public events.

    Maybe you could setup an RSS feed for all 3. 

    http://intructor/events.rss
    http://students/events.rss
    http://public/events.rss

    Then you could aggregate the feeds onto a single page appropriately depending on the web site:

    Instructors events page:
      - Click here for instructor events.
      - Click here for student events.
      - Click here for public events.

    Student events page:
      - Click here for student events.
      - Click here for public events.

    Public events page:
      - Public events.


    With this method the events would not be co-mingled in a single list.  Rather they would be separated.  I'm not sure how set in stone your design requirements are. 

    Gabe Sumner

     

  11. Joe
    Joe avatar
    138 posts
    Registered:
    24 Sep 2012
    26 Sep 2008
    Link to this post
    Hello Randal,

    Thanks for contacting us.

    As you know, Sitefinity can use controls with a text property to add a new meta field. Simply give the control's ID property the same name as the database field and the control will be bound. All of these controls with a .Text property implement the ITextControl interface. If you try to use a control that does not have a .Text property, then you get that error about an ITextInterface shown below. If you try to implement a RadEditor as a meta field, you'll notice that it has no text property. So how can it be implemented as a meta field? The process it simple and can be done by following these steps:

    1. Add a RadEditor to a User Control
    2. Create a public property called text and bind it to the RadEditor's content property as shown below:

    public string Text
        {
            get { return RadEditorMeta.Content; }
            set { RadEditorMeta.Content = value; }
        }

    3. Add the user control to one of the module templates, such as the News Module's Insert News Story ~\Sitefinity\Admin\ControlTemplates\News\ControlPanelInsert.ascx

    As for the categories problem, I am not sure what would cause this error. Can you send us some code? How are you trying to extend the categories feature of that module?

    Feel free to contact us if you need further assistance.

    All the best,
    Joe
    the Telerik team

    Check out Telerik Trainer, the state of the art learning tool for Telerik products.
Register for webinar
11 posts, 0 answered