More in this section

Forums / Developing with Sitefinity / How to get content URL in SaveContent() for new items?

How to get content URL in SaveContent() for new items?

6 posts, 1 answered
  1. bemara57
    bemara57 avatar
    135 posts
    Registered:
    27 Mar 2008
    24 Mar 2010
    Link to this post
    For my Events, I am trying to send the URL to Twitter via web services. I do this by overriding SaveContent() for EventsItemEdit.cs. I do my logic before it hits the base.SaveContent(). It works great when editting an item, but it really needs to work for creating items.

    The ID and URL of the content doesn't get created until it does it's logic in base.SaveContent(). I would love to do my Twitter logic after base.SaveContent(), but it seems there is a redirect inside base.SaveContent() so it never exits the method to reach my code.

    Any ideas on how I can get content URL during creation (base.MetaFields.Content is null throughout the who page lifecycle)? Below is what I have so far:

    protected override void SaveContent()
    {
        string eventUrl = "http://" + this.Context.Request.ServerVariables["SERVER_NAME"] + Utility.ResolveItemUrl("~/Events/View.aspx", base.MetaFields.Content.UrlWithExtension);
        //SHORTEN URL IF NOT DONE BEFORE
        var txtShortUrl = base.MetaFields.GetControl("ShortUrl", true) as ITextControl;
        if (txtShortUrl.Text.Length > 0)
        {
            eventUrl = txtShortUrl.Text;
        }
        else
        {
            try
            {
                //ATTEMPT TO SHORTEN URL VIA BITLY SERVICE
                string login = (string)this.Context.Profile.GetPropertyValue("Bitly.Login");
                string apiKey = (string)this.Context.Profile.GetPropertyValue("Bitly.Key");
                if (!String.IsNullOrEmpty(login) && !String.IsNullOrEmpty(apiKey))
                {
                    eventUrl = API.Bit(login, apiKey, eventUrl, "Shorten");
                    //SAVE IT TO TEXTBOX FOR STORAGE
                    txtShortUrl.Text = eventUrl;
                }
            }
            catch (Exception ex)
            {
                //DO LOGGING HERE
            }
        }
        //POST TO TWITTER
        var chkTwitterPost = base.MetaFields.GetControl("TwitterPost", true) as CheckBox;
        if (chkTwitterPost.Checked)
        {
            try
            {
                //UPDATE TWITTER STATUS
                string login = (string)this.Context.Profile.GetPropertyValue("Twitter.Username");
                string password = (string)this.Context.Profile.GetPropertyValue("Twitter.Password");
                if (!String.IsNullOrEmpty(login) && !String.IsNullOrEmpty(password))
                {
                    string hash = (base.MetaFields.GetControl("TwitterHash", true) as ITextControl).Text;
                    if (hash.Length > 0)
                    {
                        hash = " " + hash;
                    }
                    //BUILD STRING ACCORDING TO TWITTER CHARACTER LIMIT
                    string data = " " + eventUrl + hash;
                    int charsLeft = 140 - data.Length;
                    if (this.Title.Length > charsLeft)
                    {
                        data = this.Title.Substring(0, charsLeft) + data;
                    }
                    {
                        data = this.Title + data;
                    }
                    ServicePointManager.Expect100Continue = false;
                    Twitter twit = new Twitter();
                    twit.Update(login, password, data, Twitter.OutputFormatType.JSON);
                    //RECORD DATE OF TWITTER POST
                    (base.MetaFields.GetControl("TwitterPostDate", true) as ITextControl).Text = DateTime.Now.ToLongDateString() + ", " + DateTime.Now.ToShortTimeString();
                }
            }
            catch (Exception ex)
            {
                //DO LOGGING HERE
            }
        }
        base.SaveContent();
    }

  2. Radoslav Georgiev
    Radoslav Georgiev avatar
    3370 posts
    Registered:
    01 Feb 2016
    25 Mar 2010
    Link to this post
    Hello bemara57,

    Thank you for using our services.

    There is a way to do this without overriding the SaveContent method and will will work from one place. You can subscribe to the EventsManager.Executed event which will allow you to get the url because metafields have been already saved in the SaveContent method. To do this edit your Global.asax file like this:
    void Application_Start(object sender, EventArgs e)
    {
        Telerik.Events.EventsManager.Executed += new EventHandler<Telerik.ExecutedEventArgs>(EventsManager_Executed);
    }
     
    void EventsManager_Executed(object sender, Telerik.ExecutedEventArgs e)
    {
        if(e.CommandName=="CreateContent" || e.CommandName=="UpdateContent")
        {
            Telerik.Events.EventsManager eventsManager = new Telerik.Events.EventsManager("Events");
            Telerik.Cms.Engine.IContent content = eventsManager.Content.GetContent(e.ItemID);
            if (content != null)
            {
                string path = content.UrlWithExtension;
            }
        }
    }

    Then restart the website in order to subscribe to the event execution.

    Greetings,
    Radoslav Georgiev
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
    Answered
  3. bemara57
    bemara57 avatar
    135 posts
    Registered:
    27 Mar 2008
    25 Mar 2010
    Link to this post
    Thanks for the help. But ouch, the Global.asax? Maybe a last resort... is there a Sitefinity method that generates the URL based on the provider configurations? I am sure there is, but I could not find it anywhere. I started on a method that generates the URL of the Event, but am hoping I can use a built-in method for this. Here's what I got so far:

    public static string GetItemUrl(ContentMetaFields metaContent, string singleItemPage, bool resolveAsAbsoluteUrl)
    {
        HttpContext context = HttpContext.Current;
        string url = String.Empty;
     
        if (metaContent.Content != null)
        {
            url = ResolveItemUrl(singleItemPage, metaContent.Content.UrlWithExtension);
        }
        else
        {
            //SINCE ITEM IS NEW AND DOES NOT EXIST IN STORAGE,
            //MUST MANUALLY BUILD URL BASED ON PROVIDER RULES
            string ext = metaContent.ContentManager.Provider.UrlRewriteFormat.Substring(metaContent.ContentManager.Provider.UrlRewriteFormat.LastIndexOf('.'));
            string[] urlFormatParts = metaContent.ContentManager.Provider.UrlRewriteFormat.Substring(0, metaContent.ContentManager.Provider.UrlRewriteFormat.LastIndexOf(ext)).Split('/');
            Regex regex = new Regex(metaContent.ContentManager.Provider.UrlReplaceSymbolsRegEx);
            //string titleUrl = regex.Replace(this.Title, metaContent.ContentManager.Provider.UrlWhitespaceChar);
            foreach (string item in urlFormatParts)
            {
                url += "/" + metaContent.GetControl(item.TrimStart('[').TrimEnd(']'), true); //get value somehow, maybe a long switch statement
            }
            url += ext;
        }
     
        if (resolveAsAbsoluteUrl)
        {
            url = "http://" + context.Request.ServerVariables["SERVER_NAME"] + url;
        }
     
        return url;
    }

    Then I have this in the override SaveContent():

    string eventUrl = Utility.GetItemUrl(this.MetaFields, DEFAULT_EVENT_PAGE, true);

    Is my attempt a lost cause?
  4. bemara57
    bemara57 avatar
    135 posts
    Registered:
    27 Mar 2008
    25 Mar 2010
    Link to this post
    I was thinking about it and what I suggested about generating a URL doesn't seem so solid because it is not taking into account duplicate titles. Also is pretty messy.

    I ended up using your solution because I realized that it worked when registering EventsManager_Executed in InitializeControls of EventsItemNew.

    Thanks again!
  5. Radoslav Georgiev
    Radoslav Georgiev avatar
    3370 posts
    Registered:
    01 Feb 2016
    26 Mar 2010
    Link to this post
    Hi bemara57,

    I am happy to see that you have managed to resolve this. If you  have more questions please feel free to contact us.

    All the best,
    Radoslav Georgiev
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  6. bemara57
    bemara57 avatar
    135 posts
    Registered:
    27 Mar 2008
    26 Mar 2010
    Link to this post
    Much appreciated. I wrote an article of the entire solution to get Sitefinity to update Twitter status with Bitly shortening the URL. It works great! I hope it helps your team and the community:

Register for webinar
6 posts, 1 answered