Friday, November 28, 2014

Could not load file or assembly 'MySQL.Data' or one of its dependencies. Access is denied.



It is very common error with .net assemblies. When someone included dlls from outside, in the project, this kind of exceptions are generic.

Here is the resolution.
  1. Open the file location (MySql.Data.dll in this case)
  2. Right click on dll and check its properties (it should not be encrypted and should have right access permissions)
  3. Run the project after assigning appropriate permissions. It should work now.


Even after this if it does not work. Check in web.config that assembly information is added under <compilation> tag.

It is advisable to included new dlls using nuget package reference. It will update its reference automatically.

Happy Coding!!!

Monday, October 13, 2014

Google search appliance (GSA) sorting and filtering

Working with Google Search Appliance(GSA), sometimes business has requirement of sorting or filtering the results. Browsing the internet did not provide any helpful pointers for the ways to sort or filter the search results therefore I have written these instructions to use sorting & filtering in easy way with examples.

Sorting:
Google Search Appliance(GSA) has provided the tags to sort the results in ascending or descending order. Pages should have meta tags which provides information to GSA box for crawling. Using those tags, sorting can be achieved.

For example: If web pages has a tag

<meta name="title" content="Sumit Bajaj::Passionate Technologist" />

GSA URL should include parameter to sort the results

&sort=meta:title:a  (for arranging all results in ascending order w.r.t title)
&sort=meta:title:d  (for arranging all results in descending order w.r.t title)

Similarly it can be sorted for another meta tags.


Filtering:
Similar like sorting meta tags can be used for filtering as well. Google Search Appliance(GSA) has provided the provision to filter the results too. Pages should have meta tags which provides information to GSA box for crawling. These tags can be used for filtering the output.

For example: If web pages has a tag

<meta name="articledate" content="2014-10-12" />

GSA URL should include parameter to filter the results

&query=inmeta:articledate:daterange:2014-01-01..
(all article whose articledate is greater than 2014-01-01)

&query=inmeta:articledate:daterange:2013-01-01..2014-01-01
(all article whose articledate is in between 2013-01-01 & 2014-01-01)

&query=inmeta:articledate:daterange:..2014-01-01 
(all article whose articledate is lesser than 2014-01-01)

Similarly we can modify the tags and syntax to get desired output.

Reference:
Google Search Appliance document

For more details, you can contact me on "email.bajaj@gmail.com" or visit my website
http://www.bajajsumit.com

Enjoy coding and build the best.
Sumit Bajaj

Thursday, September 11, 2014

Host Angular App on Heroku

Angular is one of the javascript frameworks which provides new dimensions of writing javascript and on the other hand Heroku is a web hosting platform which allows applications to host. Most importantly, it gives option to host various applications free of cost.

Now considering that an angular project is ready and need to be hosted somewhere so could be accessed publicly. There are few steps which will push the project on Heroku platform and enable the angular project to be browsed by outside world.

Pre-requisite:
1. You should have a Heroku account, if not create one.
2. Heroku toolbelt is installed on machine. Once installed using command prompt, enter
"heroku login" and provide your email and password to log into heroku account.
3. In case you need some domain name, register it in advance. Otherwise you can access the URL which Heroku provides by default.
4. Last and most important point, you should be ready with angular project. Insure that you are not getting any error while running commands like "grunt build" or "grunt serve".

Lets start to host it on Heroku:
1. Run the command "grunt build" on your angular project. Once succeed, it will create a "dist" folder in your project with compiled code and clean structure.

2. Heroku need a server to serve the files. As angular project only has static files, we will use Node server for serving the file.

Create a web.js file and keep it in root directory of project. Put the mentioned lines in that file and save it.
var gzippo = require('gzippo');
var express = require('express');
var app = express();

app.use(express.logger('dev'));
app.use(gzippo.staticGzip("" + __dirname + "/dist"));
app.listen(process.env.PORT || 5000);


3. Now create a procfile (without any extension) and keep it in root directory as well. Put the mentioned lines in that file and save it.
web: node web.js


Note: "procfile" is starting point of application and lines written in it is telling node server to execute "web.js" file which internally is serving content from "dist" folder.

4. Run command "heroku create [app_name]"
It will create a project on heroku.

5. After adding file using "git add ." and committing using "git commit m 'initial commiy'", push it to heroku using command
 > git push heroku master

6. It will push the project on Heroku project and give you the heroku path to browse the website. For instance, http://abc.herokuapp.com

You are done!!

In case some specific domain name is required to point to this app, can be done easily by providing CName and pointing to heroku app.


Please provide your feedback or email me to "email.bajaj@gmail.com" for any query.


Thursday, July 31, 2014

Get ASP.NET Web API to return JSON instead of XML


By default, Web API produces XML but if there is need for JSON, given syntax will do it.

Open WebApiConfig.cs file in solution and add mentioned line in it as shown in example.

public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            //To produce JSON format add this line of code
            config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
        }

Kindly provide your valuable comments if you find the post helpful.

Friday, June 27, 2014

Custom control in Sitecore

Although Sitecore has provided most of the features out of box, yet sometime we need custom control to be created as per project need. In the given example, we will create a custom control "Pubish with media". Purpose of this custom button is to publish the content including media associated with it.

Follow the mentioned steps to make custom control.

Step1:
Create a cs file in your project and name it as "PublishWithMedia.cs". Open the file and write the code. In this example,  we are showing code for publishing media with content item.

using System;
using System.Collections.Specialized;
using Sitecore;
using Sitecore.Data;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Globalization;
using Sitecore.Links;
using Sitecore.Publishing;
using Sitecore.Shell.Framework;
using Sitecore.Shell.Framework.Commands;
using Sitecore.Web.UI.Sheer;
using Sitecore.Workflows;

namespace MyProject.CustomControl
{
    /// <summary>
    /// Represents the Publish Item command.
    /// </summary>
    [Serializable]
    public class PublishWithMedia : Command
    {
        /// <summary>
        /// Checks the workflow.
        /// </summary>
        /// <param name="args">The arguments.</param>
        /// <param name="item">The item.</param>
        /// <returns>The workflow.</returns>
        private static bool CheckWorkflow(ClientPipelineArgs args, Item item)
        {
            Assert.ArgumentNotNull(args, "args");
            Assert.ArgumentNotNull(item, "item");
            if (args.Parameters["workflow"] == "1")
            {
                return true;
            }
            args.Parameters["workflow"] = "1";
            if (args.IsPostBack)
            {
                if (args.Result != "yes")
                {
                    args.AbortPipeline();
                    return false;
                }
                args.IsPostBack = false;
                return true;
            }
            IWorkflowProvider workflowProvider = Context.ContentDatabase.WorkflowProvider;
            if (workflowProvider == null || (int)workflowProvider.GetWorkflows().Length <= 0)
            {
                return true;
            }
            IWorkflow workflow = workflowProvider.GetWorkflow(item);
            if (workflow == null)
            {
                return true;
            }
            WorkflowState state = workflow.GetState(item);
            if (state == null)
            {
                return true;
            }
            if (state.FinalState)
            {
                return true;
            }
            args.Parameters["workflow"] = "0";
            object[] displayName = new object[] { item.DisplayName, state.DisplayName };
            SheerResponse.Confirm(Translate.Text("The current item \"{0}\" is in the workflow state \"{1}\"\nand will not be published.\n\nAre you sure you want to publish?", displayName));
            args.WaitForPostBack();
            return false;
        }

        /// <summary>
        /// Executes the command in the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        public override void Execute(CommandContext context)
        {
            if ((int)context.Items.Length == 1)
            {
                Item items = context.Items[0];
                NameValueCollection nameValueCollection = new NameValueCollection();
                nameValueCollection["id"] = items.ID.ToString();
                nameValueCollection["language"] = items.Language.ToString();
                nameValueCollection["version"] = items.Version.ToString();
                nameValueCollection["workflow"] = "0";
                Context.ClientPage.Start(this, "Run", nameValueCollection);
            }
        }

        /// <summary>
        /// Queries the state of the command.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns>The state of the command.</returns>
        public override CommandState QueryState(CommandContext context)
        {
            if ((int)context.Items.Length != 1)
            {
                return CommandState.Hidden;
            }
            return base.QueryState(context);
        }

        /// <summary>
        /// Runs the specified args.
        /// </summary>
        /// <param name="args">The arguments.</param>
        protected void Run(ClientPipelineArgs args)
        {
            Assert.ArgumentNotNull(args, "args");
            string item = args.Parameters["id"];
            string str = args.Parameters["language"];
            string item1 = args.Parameters["version"];
            if (!SheerResponse.CheckModified())
            {
                return;
            }
            Item currItem = Context.ContentDatabase.Items[item, Language.Parse(str), Sitecore.Data.Version.Parse(item1)];
            Database targetDB = Sitecore.Configuration.Factory.GetDatabase("web");
            if (currItem == null)
            {
                SheerResponse.Alert("Item not found.", new string[0]);
                return;
            }
            if (!PublishWithMedia.CheckWorkflow(args, currItem))
            {
                return;
            }
            string[] strArrays = new string[] { AuditFormatter.FormatItem(currItem) };
            Log.Audit(this, "Publish item: {0}", strArrays);
            Items.Publish(currItem);

            ItemLink[] itemLinks = currItem.Links.GetValidLinks();

            foreach (ItemLink link in itemLinks)
            {
                Item itm = link.GetTargetItem();
                if (itm != null)
                {
                    if (itm != null && itm.Paths.IsMediaItem)
                    {                       
                        PublishItem(itm, targetDB);
                    }
                }
                count++;
            }
        }

        private void PublishItem(Item item, Database targetDB)
        {
            PublishOptions options = new PublishOptions(item.Database, targetDB, PublishMode.SingleItem, item.Language, DateTime.Now);
            options.RootItem = item;
            options.Deep = false;
            new Publisher(options).Publish();
        }
    }
}


Build the project to check if any errors.

Step2:
Open "Commands.config" file in App_Config folder. Click on "View all files" in Visual studio if App_Config folder is not there.

Copy the line in Commands.config file somewhere in the middle.

<command name="contenteditor:publishwithmedia" type="MyProject.CustomControl.PublishWithMedia,MyProject.CustomControl"/>


Note: Change the namespace and class name if you kept the names different.

Step3:
Open Sitecore instance and switch to "Core" database. Click on Database icon on bottom right corner of website for switching to Core database.












Open Sitecore-> Content Editor and Expand the tree to
sitecore -> content -> Applications -> Content Editor -> Ribbons -> Chunks -> Publish

Copy the existing item and create a new one. Rename it to "Publish with media". Open newly created item and in Data section of it fill mentioned information.












Header information will be displayed as Custom control name on main UI. In click section, we have mentioned "contenteditor:publishwithmedia" which is command name we added in commands.config file.

Save the item and switched back to master database as shown in start of Step 3.

Step4:
Open Sitecore -> Content Editor. Click on Publish menu and you will see custom button appearing on it.





Click on button to check the functionality. Select any item and publish with custom button, it will publish the item and media associated with item to.

Please provide your valuable comments.

Thursday, May 22, 2014

Github cherry picking

What is cherry picking ?
Cherry picking is plucking selective code to push to another branch. Sometime team is working on several modules and there is urgency to fix some production issue and deploy it.

We can have two ways of doing it
1. Create a separate branch from master (production branch) , for example name it as "branch1" and fix the bug and merge that branch into master back.

2. Fix the bug in existing branch and cherry pick it in master branch. This way only selective changes would be pushed to master and not all code.

Whenever we push some code in git, it creates a unique commit id.
For example:


Unique commit id looks like shown in green box



Copy that commit id which you want to cherry pick.
Git checkout to master branch (where you want to cherry pick)

$ command: git checkout master

Cherry pick the selected commit by passing commit id.

$ git cherry-pick b38adf46f21c963b6e85a804ef3942ad8d0b4e4d

Selected commit will be merged into master
Now you can check the status and push the code respectively.

Note: Cherry pick should be incremental and sequence wise. First commit should be cherry picked first followed by second and so on. 

Have a great day ahead !!

Wednesday, April 16, 2014

Add Rich Text Full Editor in Sitecore template

It is very common requirement and very easy to add Rich Text Full editor in Sitecore.

Steps:
1. Open Template and make the field as "Rich Text" field


Rich Text Full Editor






2. Add "/sitecore/system/Settings/HTML Editor Profiles/Rich Text Full" to the source field next to it.

3. Save the template and that's it.

Create item with the new template and click on "Show Editor" link. It should show rich text full editor.


Provide your valuable comments if this post resolved your problem.

Tuesday, March 4, 2014

Creating angular project at snap of fingure


Open CMD prompt (Run as Administrator)




Goto directory (where you want to create website) and type
yo angular:project_name



You are done!! It will create all dependent files in the directory.



If you are using IIS server, create a website and point it to directory/app folder. Browse the website for example: http://localhost, it will show you beautiful index page.

Pre-Requisite: 
Yeoman (the scoffolding tool) should be installed. Refer Yoeman website for more details.


Common Issue: When scoffolding angular project using yo command, if in between you are receiving errors, then execute this line on CMD prompt;

C:\MyProject>git config --global url."https://" .insteadOf git://

Author: Sumit Bajaj

Thanks for reading!!

Thursday, February 20, 2014

HTTP Error 500.19 - Internal Server Error

The requested page cannot be accessed because the related configuration data for the page is invalid.

<staticContent>
     <mimeMap fileExtension=".woff" mimeType="application/font-woff"/>
</staticContent>

This error occurs when there is a problem reading the configuration file for the Web server or Web application. In some cases, the event logs may contain more information about what caused this error.

Solution:
1. Open IIS and click on hosted website
2. On the Featured View tab, double click on MIME type icon and check if .woff extension is present. If on click it gives error not to worry.
3. Open web.config file of project solution and check if .woff mimemap entry is present. If yes, remove that entry.
4. Go back to IIS and follow Step 1 and Step 2. It should show .woff extension now.
5. Check your website and it should work now.

Author: Sumit Bajaj

Thanks for Reading. Have a great time.




Tuesday, February 11, 2014

Uploading an Excel and Importing the data in database

This is very common requirement to read the data from uploaded excel and import it in database. Earlier it was a tedious task but not now, thanks to Nuget packages where you get so many utilities to make your life easy. In this post, we will also use Nuget package and perform the task of uploading excel and importing the data in database.

There are two steps to perform this,
1. To upload the excel file on server
2. Read the uploaded file and import the data to database

Step1: To upload the excel file on server

   <asp:FileUpload ID="excel_upload" runat="server"/>


    
    if (excel_upload.HasFile)
    {
       bool upload_file = true;
       string file_upload = Path.GetExtension(excel_upload.FileName.ToString());
       if (file_upload.Trim().ToLower() == ".xls" | 
            file_upload.Trim().ToLower() == ".xlsx")
       {
          // Save excel file onto Server
          xlsUpload.SaveAs(Server.MapPath("~/Uploads/" + excel_upload.FileName.ToString());
       }
    }


Step2: Read the uploaded file and import the data to database

To perform excel read/write, we will use ClosedXML (Nuget package). Install the package using package manager.



Once installed, include the namespace in your code file   using ClosedXML.Excel;

Now the code starts to get data from uploaded excel file.

      FileInfo fi = new FileInfo(filePath);

      //Open uploaded workbook
            var workBook = new XLWorkbook(fi.FullName);
      //Get the first sheet of workbook
      var worksheet = workBook.Worksheet(1);

      var firstRowUsed = worksheet.FirstRowUsed();
      var categoryRow = firstRowUsed.RowUsed();

      int coCategoryId = 1;

      //Get the column names from first row of excel
      Dictionary<int, string> keyValues = new Dictionary<int, string>();
      for (int cell = 1; cell <= categoryRow.CellCount(); cell++)
      {
        keyValues.Add(cell, categoryRow.Cell(cell).GetString());
      }

      //Get the next row
      categoryRow = categoryRow.RowBelow();
      while (!categoryRow.Cell(coCategoryId).IsEmpty())
      {
         int count = 1;
         var pc = new ExpandoObject();
         while (count <= categoryRow.CellCount())
         {
          // let this go through-if the data is bad, it will be rejected by SQL
           var data = categoryRow.Cell(count).Value;

           ((IDictionary<string, object>)pc).Add(keyValues[count], data);           

           count++;
         }
         categoryRow = categoryRow.RowBelow();
      }
      //Insert the data in SQL which is captured in pc object.


Reference: To get more detailed scenarios for excel data manipulation, click here.


~~ Happy Coding ~~