Asif Maniar

Software Engineer
posts - 16 , trackbacks - 0

Friday, February 10, 2012

A Simple implementation of the Decorator Design Pattern using C#

The main motivation before the decorator pattern is to be able to add data and behavior to objects dynamically
without relying on inheritance.

A decorator usually conforms to the interface of the component its decorating.
Lets see this with an example.

Am building a system that calculates the price of a pizza. I can have many toppings and the total price of
the pizza is calculated based on what toppings I pick. One way to do this would be to use inheritance and
class hierarchies like Pizza, CheesePizza, ChickenPizza etc…which can get very inflexible.

A better way is to implement this using decorators. Below PizzaWithCheese decorates
the Pizza and adds the price of cheese to the total and so does the PizzaWithChicken.
When executed you should see the following output:

Total for cheese pizza: 15
Total for chicken pizza: 16
Total for cheese + chicken pizza: 21

 class DecoratorPattern
    {
        private interface IPizza
        {
            int GetPrice();
        }
 
        private class Pizza : IPizza
        {
            public int GetPrice()
            {
                return 10;
            }
        }
 
        //Decorator 1
        private class PizzaWithCheese : IPizza
        {
            private IPizza _pizza;
            private int _priceofCheese;
 
            public PizzaWithCheese(IPizza pizza, int priceofCheese)
            {
                _pizza = pizza;
                _priceofCheese = priceofCheese;
            }
 
            public int GetPrice()
            {
                //get price of the base pizza and add price of cheese to it
                return _pizza.GetPrice() + _priceofCheese;
            }
        }
 
        //Decorator 2
        private class PizzaWithChicken : IPizza
        {
            private IPizza _pizza;
            private int _priceofChicken;
 
            public PizzaWithChicken(IPizza pizza, int priceofChicken)
            {
                _pizza = pizza;
                _priceofChicken = priceofChicken;
            }
 
            public int GetPrice()
            {
                //get price of the base pizza and add price of chicken to it
                return _pizza.GetPrice() + _priceofChicken;
            }
        }
 
 
        public static void Test()
        {           
            var pizzaWithCheese = new PizzaWithCheese(new Pizza(), 5);
            var pizzaWithChicken = new PizzaWithChicken(new Pizza(), 6);
 
            //pizza with chicken and cheese is easy to build now.
            //we can keep decotaring the base pizza with as many decorators as necessary at runtime
            var pizzaWithChickenAndCheese = new PizzaWithChicken(pizzaWithCheese, 6);
 
            Console.WriteLine("Total for cheese pizza: " + pizzaWithCheese.GetPrice());
            Console.WriteLine("Total for chicken pizza: " + pizzaWithChicken.GetPrice());
            Console.WriteLine("Total for cheese + chicken pizza: " + pizzaWithChickenAndCheese.GetPrice());
        }
    }

Posted On Friday, February 10, 2012 4:05 PM | Comments (1) | Filed Under [ design patterns C# Software Architecture ]

Tuesday, February 7, 2012

A Simple implementation of the Proxy Design Pattern using C#

A proxy is an object that can be used to control creation and access of a more complex object thereby deferring the cost of
creating it until the time its needed.

Below is a simple implementation of the proxy pattern in C#. The ComplexProtectedExpensiveResource is private to the
ProxyContainer and cannot be instantiated by a client. The client creates an instance of the SimpleProxy class which controls
its access to the more complex and expensive to create ComplexProtectedExpensiveResource class.

Note that the ComplexProtectedExpensiveResource is created by the SimpleProxy instance only when needed and after
verifying that the client indeed has access to it.

 

namespace Patterns
{
    class ProxyContainer
    {
        private class ComplexProtectedExpensiveResource
        {
            internal void DoWork()
            {
                //do some heavy lifting
            }
        }

        // The Proxy
        public class SimpleProxy
        {
            ComplexProtectedExpensiveResource _complexProtectedResource;
            private string _password;

            public SimpleProxy(string password)
            {
                _password = password;
            }

            public void DoWork()
            {
                if (Authenticate())
                {
                    _complexProtectedResource.DoWork();    
                }
            }

            bool Authenticate()
            {
                //authenticate request
                if (_password == "password")
                {
                    //create expensive object if authenticated
                    if (_complexProtectedResource == null)
                        _complexProtectedResource = new ComplexProtectedExpensiveResource();
                    return true;
                }
                return false;
            }
        }
    }

    // The Client
    class ProxyPattern : ProxyContainer
    {
        static void DoWork()
        {
           var simpleProxy = new SimpleProxy("password");
           simpleProxy.DoWork();
        }
    }
}

Posted On Tuesday, February 7, 2012 4:02 PM | Comments (1) | Filed Under [ design patterns C# ]

Monday, December 12, 2011

Using Sitecores pipeline to pre-populate item in current language

Sitecore has a powerful event pipeline infrastructure that you can leverage to plugin commands into various item creation, change, move, publish etc events.

Recently I had to add functionality to Sitecore so that when an items version is created all fields from a target language are copied into the newly created version to ease editing.

To do this first we add an event handler in the Web.Config file for the versionAdded event.

 <event name="item:versionAdded">
        <handler type="MyNamespace.MyClass, MyAssembly" method="OnVersionAdded" />
      </event>

 

Then add the OnVersionAdded event to the class added to the type attribute above.

The Method is as shown:

namespace MyNameSpace{
    public class MyClass
    {
        public void OnVersionAdded(object sender, EventArgs args)
        {
           //get item
            var item = Event.ExtractParameter(args, 0) as Item;
            try
            {
                if (item != null && item.Version.Number == 1)
                { 
                        //copy fields from fallback item
                        //we were using Language Fallback as explained below. Get whatever sourceItem you want to use 
                        var fallbackItem = FallbackLanguageManager.GetFallbackItem(item, false);

                        item.Editing.BeginEdit();
                        fallbackItem.Fields.ReadAll();
                        //copy over all fields from source to target language
                        foreach (Sitecore.Data.Fields.Field field in fallbackItem.Fields)
                        {
                            if (!field.Shared && !field.Name.StartsWith("__") && field.Name.Trim() != "")
                            {
                                item.Fields[field.Name].SetValue(field.Value, true);
                            }
                        }
                        item.Editing.EndEdit();
                        item.Editing.AcceptChanges();
                    }
                }
            }
            catch (Exception exception)
            {
                Sitecore.Diagnostics.Log.Error("Application Error", exception, this);
                if (item != null)
                { 
                    item.Editing.CancelEdit(); 
                }
            }
    }
}
 
Note that above code uses a FallbackLanguageManager to get the fallback item. 
This is basically the current item in the fallback language configured for the current language.
This is based on the Fallback provider released by Alex Shyba at Sitecore:
http://sitecoreblog.alexshyba.com/2010/11/approaching-language-fallback-with.html
 
If you are not using the fallback simply change the line to get the Item from the desired source language like:
var fallbackItem = item.Database.GetItem(item.ID, Language.Parse("en"));
 
Code for the FallbackLanguageManager (borrowed from Alex’s fallback provider source)
 
public class FallbackLanguageManager
    {
        public static Item GetFallbackItem(Item item, bool forceFallback)
        {
            var fallbackLanguage = GetFallbackLanguage(item.Language, item.Database);
            var enforcedFallbackLanguage = Language.Parse("en");

            if (fallbackLanguage != null && !String.IsNullOrEmpty(fallbackLanguage.Name) && !fallbackLanguage.Equals(item.Language))
            {
                return item.Database.GetItem(item.ID, fallbackLanguage, Version.Latest);
            }

            if (forceFallback && !item.Language.Equals(enforcedFallbackLanguage))
            {
                return item.Database.GetItem(item.ID, enforcedFallbackLanguage, Version.Latest);
            }

            return null;
        }

        public static Language GetFallbackLanguage(Language language, Database database)
        {
            var sourceLangItem = GetLanguageDefinitionItem(language, database);
            return sourceLangItem != null ? GetFallbackLanguage(sourceLangItem) : null;
        }

        public static Item GetLanguageDefinitionItem(Language language, Database database)
        {
            var sourceLanguageItemId = LanguageManager.GetLanguageItemId(language, database);
            return ID.IsNullOrEmpty(sourceLanguageItemId) ? null : ItemManager.GetItem(sourceLanguageItemId, Language.Parse("en"), Version.Latest, database, SecurityCheck.Disable);
        }

        protected static Language GetFallbackLanguage(Item langItem)
        {
            var fallbackLangName = langItem[SitecoreFields.FallbackLanguage];
            Language fallbackLang;
            return Language.TryParse(fallbackLangName, out fallbackLang) ? fallbackLang : null;
        }
    }
 
Hope this helps!

Posted On Monday, December 12, 2011 5:41 PM | Comments (0) |

Monday, October 24, 2011

Removing / Restricting Access to Sitecores Interface on Content Delivery Environments

Here are a few steps you can follow if you want to restrict access to Sitecore’s Interface on content delivery environments.

1) Open Internet Information Services (IIS) Manager

2) Expand your Content Delivery website

3) Click on the Sitecore folder

4) Double Click on Authentication in the middle content pane

 

image

 

5) In the Authentication Pane right click Anonymous Authentication and click Disable

image

 

6) Try visiting the Sitecore login page on the Content Delivery site and verify that you get an access denied exception

image

 

7) You might also want to copy the yourwebroot/sitecore/service folder into the webroot and update the paths in the web.config file for the various error pages.

 

Hope this helps.

Posted On Monday, October 24, 2011 5:40 PM | Comments (0) |

Monday, April 18, 2011

Mix 2011 Session List using OData, datajs and jQuery

At the recent Mix 2011 conference the datajs team talked about this new cross-browser JavaScript library that makes writing data centric web apps easier.

Its fairly simple to use and can be very powerful.

Here is a quick application I threw together using the library. The code uses datajs, jQuery, jQuery UI and jQuery templates.

Microsoft has an OData Service at http://live.visitmix.com/odata/Sessions which exposes all Mix sessions. I used this source to get a list of all sessions using the datajs library and bound them to a template using the templating library.

The below code uses the OData.read function to read the list of sessions and then binds the results to the sessionTemplate template.

//enable jsonp since this is a cross dom
OData.defaultHttpClient.enableJsonpCallback = true;
//read all sessions and bind to sessionsTemplate
OData.read("http://live.visitmix.com/odata/Sessions?$orderby=Title asc",
      function (data, request) {
       results = data.results;
              $("#sessionTemplate").tmpl(
              results,
              {
                  getTags: getTags
              }
).appendTo("#sessionList");
 

The getTags method is passed into the template so the tags can be loaded for each session when it renders.

function getTags(sessionId) {
       //get list of all tags for this session
       OData.read("http://live.visitmix.com/odata/Sessions(" + sessionId + ")/Tags",
        function (data, request) {
              //bind to the tagTemplate
              $("#tagTemplate").tmpl(data.results).appendTo("#" + sessionId);
         });
     return "";
 }
 

Here is the sessions template:

<script id="sessionTemplate" type="text/x-jquery-tmpl">
            <li><b><a href='http://channel9.msdn.com/events/mix/mix11/${SessionCode}' target="_blank">${Title}</a></b> <p>${Abstract}</p>
                <p id='${SessionID}'>
                                              //call the getTags method to get the tags html
                    Tags: {{html $item.getTags($item.data.SessionID)}}
                </p>
            </li>
        </script>
 
The Tags template: (links to channel9 page for that tag)
<script id="tagTemplate" type="text/x-jquery-tmpl">
   <a href='http://channel9.msdn.com/Events/MIX/MIX11?t=${TagValue}' target="_blank">${TagValue}</a>&nbsp;
</script>
 
The Tags section in the sessionList template invokes the getTags function passed to it which in turn makes a request using the OData library for all tags for the current session.

Example - tags for session with ID of 150: http://live.visitmix.com/odata/Sessions(150)/Tags

I also used the jQuery autocomplete plugin to create a autocompleted textbox so users can search for a session by title.

$("#searchTextbox").autocomplete({
  source: function (request, response) {
      response($.map(results, function (item) {
       if (item.Title.toLowerCase().indexOf($.trim(request.term.toLowerCase())) != -1) {
              return {
                        label: item.Title,
                        sessionId: item.SessionID
                      }
                  }
              }))
              },
        select: function (event, ui) {
        OData.read("http://live.visitmix.com/odata/Sessions(" + ui.item.sessionId + ")",
        function (data, request) {
                $("#sessionList").empty();
                $("#sessionTemplate").tmpl(data).appendTo("#sessionList");
                });
       }
}
 

The above code uses the source method of the autocomplete plugin to populate the list of sessions and then overrides the select method to bind to the selected session.

You can read more about the autocomplete plugin here.

Note: This isnt the most efficient way of loading data as it doesnt use paging, background fetching or local storage provided by HTML5 and datajs. Just wanted to demo the odata portion of the datajs library and how it can be used.

Hope to change this to use local storage in the future.

You may view the entire sample here: http://www.asifmaniar.com/Samples/Mix-2011-sessions-using-OData-and-datajs.aspx

 

 

 

 

 

 

Posted On Monday, April 18, 2011 5:16 PM | Comments (0) |

Monday, October 25, 2010

Copying Sitecore Items across Languages

When using multiple languages/cultures in the Sitecore CMS the content of an item isn’t usually copied over from an existing language to a new language version.

While working on a multi lingual website after content was added to the primary language (en-US) I had to write a script to copy all fields from the primary language into other languages (Example en-GB).
 
Here is some code that I used for Sitecore 6.2.
 
The following method copies an item from the Source Language to a Target Language provided that the source item has at least one version. Note that if the Target Item lacks a version one is created and only the custom fields (ones not starting with a __) are copied over.
void Copy(Sitecore.Data.Items.Item item, Sitecore.Globalization.Language sourceLanguage,
             Sitecore.Globalization.Language targetLanguage)
        {
            //get a reference to the master DB
            Sitecore.Data.Database masterDB = Sitecore.Configuration.Factory.GetDatabase("master");
          
            Sitecore.Data.Items.Item targetItem = masterDB.Items[item.ID, targetLanguage];
            Sitecore.Data.Items.Item sourceItem = masterDB.Items[item.ID, sourceLanguage];
 
            if (targetItem == null || sourceItem == null || sourceItem.Versions.Count == 0)
                return;
            //Disable the security context
            using (new Sitecore.SecurityModel.SecurityDisabler())
            {
                try
                {
                    if (targetItem.Versions.Count == 0)
                    {
                  //add a version if none exist
                        targetItem = targetItem.Versions.AddVersion();
                    }
                    //edit item in target language
                    targetItem.Editing.BeginEdit();
                    sourceItem.Fields.ReadAll();
                    //copy over all fields from source to target language
                    //we omit internal fields which start with __
                    foreach (Sitecore.Data.Fields.Field field in sourceItem.Fields)
                    {
                        if (!field.Shared && !field.Name.StartsWith("__") && field.Name.Trim() != "")
                        {
                            targetItem.Fields[field.Name].SetValue(field.Value, true);
                        }
                    }
 
                    targetItem.Editing.EndEdit();
                    targetItem.Editing.AcceptChanges();
                }
                catch (Exception ex)
                {
                    targetItem.Editing.CancelEdit();
                    Response.Write(ex.Message);
                }
            }
           
The following method copies an item from a Source Language to a Target language. In this case two items can be different but are expected to have the same Fields.
 
 void Copy(Sitecore.Data.Items.Item sourceItem, Sitecore.Globalization.Language sourceLanguage,
            Sitecore.Data.Items.Item targetItem, Sitecore.Globalization.Language targetLanguage)
        {
            Sitecore.Data.Database masterDB = Sitecore.Configuration.Factory.GetDatabase("master");
 
            targetItem = masterDB.Items[targetItem.ID, targetLanguage];
            sourceItem = masterDB.Items[sourceItem.ID, sourceLanguage];
 
            if (targetItem == null || sourceItem == null || sourceItem.Versions.Count == 0)
                return;
 
            using (new Sitecore.SecurityModel.SecurityDisabler())
            {
                try
                {
                    if (targetItem.Versions.Count == 0)
                    {
                        targetItem = targetItem.Versions.AddVersion();
                    }
                    targetItem.Editing.BeginEdit();
                    sourceItem.Fields.ReadAll();
                    foreach (Sitecore.Data.Fields.Field field in sourceItem.Fields)
                    {
                        if (!field.Shared && !field.Name.StartsWith("__") && field.Name.Trim() != "")
                        {
                            targetItem.Fields[field.Name].SetValue(field.Value, true);
                        }
                    }
 
                    targetItem.Editing.EndEdit();
                    targetItem.Editing.AcceptChanges();
                }
                catch (Exception ex)
                {
                    targetItem.Editing.CancelEdit();
                    Response.Write(ex.Message);
                }
            }
 
        }
 
You can call the above methods after querying Sitecore’s Master DB for items you would like to clone.
protected void Import(object sender, EventArgs e)
        {
            try
            {
                Sitecore.Data.Database masterDB = Sitecore.Configuration.Factory.GetDatabase("master");
 
                Sitecore.Data.Items.Item[] items = Sitecore.Context.Database.SelectItems
                 ("/sitecore/content/Home/MySectionToCopy//*");
              
                //get source and target language for the copy
                Sitecore.Globalization.Language sourceLanguage = Sitecore.Data.Managers.LanguageManager.GetLanguage("en-US", masterDB);
                Sitecore.Globalization.Language targetLanguage = Sitecore.Data.Managers.LanguageManager.GetLanguage("en-GB", masterDB);
 
                if (sourceLanguage == null || targetLanguage == null)
                    return;
 
                foreach (Item item in items)
                {
                  //copy item from source to target language
                    Copy(item, sourceLanguage, targetLanguage);
                }
            }
            catch (Exception ex)
            {
                Response.Write(ex.Message);
            }
 
        }
 
Note: You also have the option to plug into Sitecore’s event pipeline and automatically copy a source language into the target language when a version is added.

Posted On Monday, October 25, 2010 5:20 PM | Comments (1) |

Wednesday, October 20, 2010

Windows 7 Phone Details for Developers

Attended the windows phone jump start event yesterday and had a chance to see some presentations and play with the new windows phone.

The Good:

  •  Xbox Live is integrated into the phone http://www.xbox.com/en-US/Live/Mobile/Home
  •  Free MS Office 2010 on the phone
  • Zune is integrated
  • GPS/Accelerometer/Camera (nothing new there)
  • All developer tools are free http://create.msdn.com/en-us/home/getting_started (comes with VS2010, Blend, XNA Studio and deployment tools)
  • .NET developers can write apps in C# & Silverlight using VS2010 and the free tools
  • Free XNA Studio for Game developers
  •  No multi tasking support but the Notifications API lets you send notifications to the phone from an external server and an application close event allows developers to save the applications state before exit
  • Launchers framework allows for fire and forget actions (like sending an SMS)
  • Choosers Framework lets you choose some piece of information (like a contact, photo or song) and drive it back to the application
  • Trial API available to offer trial of applications/games
  • Ad API available for Ad integration
  • $100/Year membership allows you to unlock 3 phones for testing apps, 5 free application submissions and unlimited paid app submissions
  • 30%-70% profit split between Microsoft and Developers for paid apps

 

Not so Good:

  • No copy/paste (might be in the next release)
  • The onboard Sql CE Server is closed to app developers for now (have to use isolated storage)
  • Bluetooth support is limited to headphones
  • Looks like you need a Win 7 / 2008 box to install the dev tools
  • No CDMA support yet (it's coming next year)

Links:

http://create.msdn.com

http://blogs.msdn.com/b/davedev/

http://www.microsoft.com/windowsphone/en-us/default.aspx

http://silverlight.codeplex.com/

http://channel9.msdn.com/blogs/egibson/windows-phone-7-jump-start-session-1-of-12-introduction

 

Posted On Wednesday, October 20, 2010 4:03 PM | Comments (1) |

Tuesday, October 12, 2010

Enabling HTTP Redirect in IIS7

If you want a virtual directory or a site in IIS7.x to redirect to another url you first have to make sure you have installed http redirect for IIS.

To do that goto Control Panel > Program and Features and select Turn Windows features on or off

 

Choose IIS and click on Add Role Services and make sure you check HTTP Redirection

 

 Let the feature be installed and configured.

Now you will see the HTTP Redirect option in the Features View of IIS.

Click HTTP Redirect and add the necessary redirect information to add a redirect for a virtual directory or an entire site.

 

Posted On Tuesday, October 12, 2010 4:00 PM | Comments (1) |

Tuesday, August 31, 2010

WCF and IIS7: 404 - File or Directory not found

Ever been puzzled by the 404 - File or Directory not found error message when deploying a WCF service to a new .NET/IIS7 installation?

The error seems to indicate that the .svc file could not be located even though it’s present in the website.

This usually is a side effect of the server not having WCF Activation feature turned on. As soon as you turn it on in the Add features wizard your WCF service will be served correctly by IIS.

 

Posted On Tuesday, August 31, 2010 4:48 PM | Comments (5) |

Tuesday, April 27, 2010

Cleaner ClientID's with ASP.NET 4.0

A common complain we have had when using ASP.NET web forms is the inability to control the ID attributes being rendered in the HTML markup when using server controls.

Our Interface Engineers want to be able to predict the ID’s of controls thereby having more control over their client side code for selecting/manipulating elements by ID or using CSS to target them.

While playing with the just released VS2010 and .NET 4.0 I discovered some real cool improvements. One of them is the ability to now have full control over the ID being rendered for server controls.

ASP.NET 4.0 controls now have a new ClientIDMode property which gives the developer complete control over the ID’s being rendered making it easy to write JavaScript and CSS against the rendered html.

By default the ClientIDMode is set to Predictable which results in clean and predictable ID’s by concatenating the ID’s of the Parent and child controls. So the following markup:

<asp:Content ID="ParentContainer" ContentPlaceHolderID="MainContentPlaceHolder" runat="server">

    <asp:Label runat="server" ID="MyLabel">My Label</asp:Label>

</asp:Content>                                                                                                                                                            

Will render:

 

<span id="ParentContainer_MyLabel">My Label</span>

Instead of something like this: (current)

<span id="ct100_ParentContainer_MyLabel">My Label</span>

Other modes include AutoID (renders ID’s like it currently does in .NET 3.5), Static (renders the ID exactly as specified in the code) and Inherit (defers the mode to the parent control).

So now I can write my jQuery selector as:

$(“ParentContainer_MyLabel”).text(“My new Text”);

Instead of:

$(‘<%=this. MyLabel.ClientID%>’).text(“My new Text”);

Scott Mitchell has a great article about this new feature:

http://bit.ly/ailEJ2

Am excited about this and some other improvements. Many thanks to the ASP.NET team for Listening!

Posted On Tuesday, April 27, 2010 10:40 AM | Comments (0) |

Powered by: