Thursday, February 28, 2013

How to add new table with model, map to nopCommerce


I am new to NopCommerce v2.4 and wondering where do I write my code (by creating new model in admin or nop.web section)
answer
I spent plenty of time for delving into this problem' depths. I can summarize the solution as follows:
  1. Create The Entity Class (e.g Entity.cs)
    Path : Nop/Core/Domain/Entity.cs
  2. Create The Mapping Class (e.g EntityMap.cs)
    Path : Nop/Data/Mapping/EntityMap.cs
  3. Create a Model for MVC (e.g EntityModel.cs)
    Path : Nop/Admin/Models/EntityModel.cs OR Nop/Web/Models/EntityModel.cs
  4. Create a validator for model (e.g EntityValidator.cs)
    Path : Nop/Admin/Validators/EntityValidator.cs OR Nop/Web/Validators/EntityValidator.cs
  5. Create A Mapping Configuration On AutoMapperStartupTask.cs for Entity and Model
    Path : Nop/Admin/Infrastructure OR Nop/Web/Infrastructure
  6. Apply Mapping between Model and Entity on MappingExtensions.cs
    Path : Nop/Admin OR Nop/Web
  7. Create a service class and service interface (e.g EntityService.cs , IEntityService.cs)
    Path : Nop/Services/EntityService.cs AND Nop/Services/IEntityService.cs
  8. Finally Create Controller and View for given model
as Nop Commerce uses the very first release of MVC3, database migration is not supported and you must make changes to database tables by hand. Because MVC code-first must drop and recreate your database for reflecting changes to your database.
If you want to get to more detail in any step, let me know - I can describe each step in detail. Hope this helps.

Wednesday, February 20, 2013

PreApplicationStartMethod on asp.net

//Contributor: Umbraco (http://www.umbraco.com). Thanks a lot!
//SEE THIS POST for full details of what this does - http://shazwazza.com/post/Developing-a-plugin-framework-in-ASPNET-with-medium-trust.aspx

[assembly: PreApplicationStartMethod(typeof(PluginManager), "Initialize")]
namespace Nop.Core.Plugins
{
    /// <summary>
    /// Sets the application up for the plugin referencing
    /// </summary>
    public class PluginManager
    {
        #region Const

        private const string InstalledPluginsFilePath = "~/App_Data/InstalledPlugins.txt";
        private const string PluginsPath = "~/Plugins";
        private const string ShadowCopyPath = "~/Plugins/bin";

        #endregion

        #region Fields

        private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
        private static DirectoryInfo _shadowCopyFolder;
        private static bool _clearShadowDirectoryOnStartup;

        #endregion

        #region Methods

        /// <summary>
        /// Returns a collection of all referenced plugin assemblies that have been shadow copied
        /// </summary>
        public static IEnumerable<PluginDescriptor> ReferencedPlugins { get; set; }

        /// <summary>
        /// Returns a collection of all plugin which are not compatible with the current version
        /// </summary>
        public static IEnumerable<string> IncompatiblePlugins { get; set; }

        /// <summary>
        /// Initialize
        /// </summary>
        public static void Initialize()
        {
            using (new WriteLockDisposable(Locker))
            {
                // TODO: Add verbose exception handling / raising here since this is happening on app startup and could
                // prevent app from starting altogether
                var pluginFolder = new DirectoryInfo(HostingEnvironment.MapPath(PluginsPath));
                _shadowCopyFolder = new DirectoryInfo(HostingEnvironment.MapPath(ShadowCopyPath));

                var referencedPlugins = new List<PluginDescriptor>();
                var incompatiblePlugins = new List<string>();

                _clearShadowDirectoryOnStartup = !String.IsNullOrEmpty(ConfigurationManager.AppSettings["ClearPluginsShadowDirectoryOnStartup"]) &&
                   Convert.ToBoolean(ConfigurationManager.AppSettings["ClearPluginsShadowDirectoryOnStartup"]);

                try
                {
                    var installedPluginSystemNames = PluginFileParser.ParseInstalledPluginsFile(GetInstalledPluginsFilePath());

                    Debug.WriteLine("Creating shadow copy folder and querying for dlls");
                    //ensure folders are created
                    Directory.CreateDirectory(pluginFolder.FullName);
                    Directory.CreateDirectory(_shadowCopyFolder.FullName);

                    //get list of all files in bin
                    var binFiles = _shadowCopyFolder.GetFiles("*", SearchOption.AllDirectories);
                    if (_clearShadowDirectoryOnStartup)
                    {
                        //clear out shadow copied plugins
                        foreach (var f in binFiles)
                        {
                            Debug.WriteLine("Deleting " + f.Name);
                            try
                            {
                                File.Delete(f.FullName);
                            }
                            catch (Exception exc)
                            {
                                Debug.WriteLine("Error deleting file " + f.Name + ". Exception: " + exc);
                            }
                        }
                    }

                    //load description files
                    foreach (var dfd in GetDescriptionFilesAndDescriptors(pluginFolder))
                    {
                        var descriptionFile = dfd.Key;
                        var pluginDescriptor = dfd.Value;

                        //ensure that version of plugin is valid
                        if (!pluginDescriptor.SupportedVersions.Contains(NopVersion.CurrentVersion, StringComparer.InvariantCultureIgnoreCase))
                        {
                            incompatiblePlugins.Add(pluginDescriptor.SystemName);
                            continue;
                        }

                        //some validation
                        if (String.IsNullOrWhiteSpace(pluginDescriptor.SystemName))
                            throw new Exception(string.Format("A plugin '{0}' has no system name. Try assigning the plugin a unique name and recompiling.", descriptionFile.FullName));
                        if (referencedPlugins.Contains(pluginDescriptor))
                            throw new Exception(string.Format("A plugin with '{0}' system name is already defined", pluginDescriptor.SystemName));

                        //set 'Installed' property
                        pluginDescriptor.Installed = installedPluginSystemNames
                            .Where(x => x.Equals(pluginDescriptor.SystemName, StringComparison.InvariantCultureIgnoreCase))
                            .FirstOrDefault() != null;

                        try
                        {
                            //get list of all DLLs in plugins (not in bin!)
                            var pluginFiles = descriptionFile.Directory.GetFiles("*.dll", SearchOption.AllDirectories)
                                //just make sure we're not registering shadow copied plugins
                                .Where(x => !binFiles.Select(q => q.FullName).Contains(x.FullName))
                                .Where(x => IsPackagePluginFolder(x.Directory))
                                .ToList();

                            //other plugin description info
                            var mainPluginFile = pluginFiles.Where(x => x.Name.Equals(pluginDescriptor.PluginFileName, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
                            pluginDescriptor.OriginalAssemblyFile = mainPluginFile;

                            //shadow copy main plugin file
                            pluginDescriptor.ReferencedAssembly = PerformFileDeploy(mainPluginFile);

                            //load all other referenced assemblies now
                            foreach (var plugin in pluginFiles
                                .Where(x => !x.Name.Equals(mainPluginFile.Name, StringComparison.InvariantCultureIgnoreCase))
                                .Where(x => !IsAlreadyLoaded(x)))
                                    PerformFileDeploy(plugin);
                           
                            //init plugin type (only one plugin per assembly is allowed)
                            foreach (var t in pluginDescriptor.ReferencedAssembly.GetTypes())
                                if (typeof(IPlugin).IsAssignableFrom(t))
                                    if (!t.IsInterface)
                                        if (t.IsClass && !t.IsAbstract)
                                        {
                                            pluginDescriptor.PluginType = t;
                                            break;
                                        }

                            referencedPlugins.Add(pluginDescriptor);
                        }
                        catch (ReflectionTypeLoadException ex)
                        {
                            var msg = string.Empty;
                            foreach (var e in ex.LoaderExceptions)
                                msg += e.Message + Environment.NewLine;

                            var fail = new Exception(msg, ex);
                            Debug.WriteLine(fail.Message, fail);

                            throw fail;
                        }
                    }
                }
                catch (Exception ex)
                {
                    var msg = string.Empty;
                    for (var e = ex; e != null; e = e.InnerException)
                        msg += e.Message + Environment.NewLine;

                    var fail = new Exception(msg, ex);
                    Debug.WriteLine(fail.Message, fail);

                    throw fail;
                }


                ReferencedPlugins = referencedPlugins;
                IncompatiblePlugins = incompatiblePlugins;

            }
        }

Friday, February 1, 2013

Splash Screen example for Silverlight

create SplashScreen.xaml in ProjectName.Web project

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignWidth="800" d:DesignHeight="600"
        x:Name="parentControl"
        Background="Black">
    <Canvas Width="300" Height="60" VerticalAlignment="Center" HorizontalAlignment="Center" >
        <Border BorderBrush="#FFAAAAAA" BorderThickness="1" HorizontalAlignment="Left" Height="10" Margin="0" VerticalAlignment="Top" Width="300" Canvas.Top="40">
            <Rectangle Fill="#FF555555" Height="10" Width="300" RenderTransformOrigin="0,0.5" HorizontalAlignment="Left" VerticalAlignment="Top">
                <Rectangle.RenderTransform>
                    <ScaleTransform x:Name="progressBar" ScaleX="0"/>
                </Rectangle.RenderTransform>
            </Rectangle>
        </Border>
        <TextBlock x:Name="status" Height="20" Canvas.Left="0" Text="Loading..." TextWrapping="Wrap" Canvas.Top="20" Foreground="#FFAAAAAA" Width="300" FontSize="13.333" HorizontalAlignment="Left" VerticalAlignment="Top" FontFamily="Arial"/>
    </Canvas>
</Grid>

create SplashScreen.js in ProjectName.Web project 


function onSourceDownloadProgressChanged(sender, eventArgs) {
    sender.findName("status").Text = "Loading: " + Math.round(eventArgs.progress * 100) + "%";
    sender.findName("progressBar").ScaleX = Math.round(eventArgs.progress * 100) / 100;
} 


default.aspx file fix below:

<script type="text/javascript" src="SplashScreen.js"></script>
</head>
<body>
    <form id="form1" runat="server" style="height:100%">
    <div id="silverlightControlHost">
        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
          <param name="source" value="ClientBin/ProjectName.xap"/>
          <param name="onError" value="onSilverlightError" />
          <param name="background" value="white" />
          <param name="minRuntimeVersion" value="5.0.61118.0" />
          <param name="autoUpgrade" value="true" />
          <param name="splashscreensource" value="SplashScreen.xaml"/>
          <param name="onSourceDownloadProgressChanged" value="onSourceDownloadProgressChanged" />
          <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=5.0.61118.0" style="text-decoration:none">
               <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>
          </a>
        </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>
    </form>
</body>
</html>

How to dynamically load internal xaml in Silverlight?

Logo.xaml
 
<Canvas
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="286.233" Height="143.425">

    <Canvas>

        <Path />

        <Path />

        <Path />

        <Path />

    </Canvas>
</Canvas>
 
 
I got this to work using build action "Resource" and the XamlLoader with a ContentControl:
 
 
var resourceName = string.Format("MyApp;component/Resources/Logos/{0}.xaml", logoName);
var uri = new Uri(resourceName, UriKind.Relative);
var streamResourceInfo = Application.GetResourceStream(uri);

string xaml = null;

using (var resourceStream = streamResourceInfo.Stream)
{
    using (var streamReader = new StreamReader(resourceStream))
    {
        xaml = streamReader.ReadToEnd();
    }
}

Canvas canvas = XamlReader.Load(xaml) as Canvas;

this.contentControl.Content = canvas;