A bit more about Using Ninject 2.2 - factory methods


(Credit: Image used is from http://fav.me/d2pz3om, if the author objects, I'll remove it immedietly)


As I understand it, Ninject 2.3 will have a .Bind<T>().ToFactory() Method. In the mean time, though, what do we do when we need to bind at run time?

Let's say we have a Ninja class, which we want to send off to... well, 'off' someone. The problem is, we don't know, at design time, if the target will be roaming around a snowy area, or somewhere dark. So which Ninja instance will we need? The one who wears white, or the one who wears black clothes?

 

    class Ninja : ISpecialForcesWarrior
    {        
        
private readonly IClothes _clothes;
        
public Ninja(IClothes clothes)
        {
            _clothes = clothes;
        }
 
        
public void SpecialKill(ITarget target)
        {

            Sneak(); //Uses _clothes
            Kill(target);

        }

 

 

In our NinjectModule Implementation, we'll bind a factory method, like so:

 

            Bind<Func<IClothesISpecialForcesWarrior>>().ToMethod(
                context =>
                clothes => Kernel.Get<
ISpecialForcesWarrior>(new ConstructorArgument("clothes", clothes)));

 

What did we do here? We bound a Func from IClothes to ISpecialForcesWarrior, instead of binding the interface directly. Again: this Func will receive the clothes as a parameter at run-time, and will return the correct instance of the ISpecialForcesWarrior.

 

Note: obviously I added the interface ISpecialForcesWarrior just for fun. You can bind the Func from Iclothes to Ninja, if it'll help your understanding.

 

The class that will instantiate the Ninja, the Daimu, will not use the warrior like this:

 

    class Daimu
    {
        
private ISpecialForcesWarrior _specialForcesWarrior;
        
public Daimu(ISpecialForcesWarrior specialForcesWarrior)
        {
            _specialForcesWarrior = specialForcesWarrior;
        }
    }

 

Instead, the Daimu will look like this:

 

    class Daimu
    {
        
private readonly Func<IClothesISpecialForcesWarrior> _specialForcesWarriorFactory;
 
        
public Daimu(Func<IClothesISpecialForcesWarrior> specialForcesWarriorFactory)
        {
            _specialForcesWarriorFactory = specialForcesWarriorFactory;
        }
 

 

 

        private void SendSpecialWarrior()
        {
            
IClothes clothes = new NinjaClothes { Color = NinjaClothesColor.Black };
            
var warrior = _specialForcesWarriorFactory(clothes);
        }

    }

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

A short summary about DI and using Ninject not as a Service Locator

Note: This post was edited on 21st December 2011, after the first comment was left by Remo Gloor .


Using Ninject in a classic DI scenario, means that only the entry point of you code should have knowledge about Ninject. This is different than using it as a Service Locator, where either
  • all classes know about the IoC Container (Ninject, in this case) and access it, meaning that every class is implicitly coupled with it.
  • or, you have to pass the Service Locator as an argument to every class's constructor, which means adding a lot of code and having classes that don't use the SL directly know about it, since they must pass it along to classes they use.
So your code-entry point configures the Kernel to be used, according to its scenario. Then what?
Well, then it uses the IoC Container to instantiate a class, or several classes, and that's it. Behind the scenes, every class called by those classes, doesn't know about the IoC Container, but declares its dependencies in its constructor. When the class is instantiated, the IoC Container will recognize the dependencies and attempt to resolve them, i.e. instantiate the classes which this class needs.

Note these following cases:
  • Class A depends on class B, but only uses it in specific situations.
  • Class A needs to return a type of class B.
  • Class A depends on Class B, but the configuration of Class B will only be known at run-time.
  • Class A will need several instances of class B, but the number of instances will only be known at run-time. 
In these cases, you might want to pass a factory method to class A's constructor. This method can be used by class A to instantiate class B. So how do you do that?

Let's use a real-life example. Class B, in this example, is AuditManager, and it implements an interface called IAuditManager.
First, we declare the factory method in the constructor of the dependent class (called "Class A", above):
...
private readonly Func <IAuditManager> _auditManagerFactory;

public SomeConstructor(Func<IAuditManager> auditManagerFactory) 
{
     _auditManagerFactory = auditManagerFactory;
}
...


As you can see, we're using Func<> to declare the delegate for the factory method.
To use the method, we simply invoke it:

   var auditManager= _auditManagerFactory();     
   auditManager.AuditSomething();


And this is how to bind the method, in the NinjectModule:

Bind<Func<IClassB>>()
.ToMethod(ctx => () => ctx.Kernel.Get<ClassB>());


  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

IoC Container != DI

Well, after reading the following article, I figured the case Paul Hiles makes is not bad. Not every one wants or needs DI, and granted, in many cases moving from a "IoC Container used as a Service Locator" solution to a "real dependency injection" solution might just be not worth it, I believe that it's a better structure, especially if you're writing from scratch. 

http://www.devtrends.co.uk/blog/how-not-to-do-dependency-injection-the-static-or-singleton-container

I'm not writing from scratch, and in fact, even bringing the software I worked on from "everything's coupled with everything's else" to "everyone knows just the one Service Locator as a global thingy" was a huge step towards an easier to read, testable code. Still, I'm looking forward to making the code even better by making all of the classes decoupled from the SL, except for the "points of entry" since I'm working on Web solutions.

Bottom line: read the article, decide if it's right for your situation - and write better code :)
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

GetFileFingerPrint method

This method is a demonstration for use of C# (csharp) Tasks and the Cache object together, to create a nice thread-safe behavior for calculations, and be efficient in the simple don't-repeat-any-action way.

        public AdsFileInfo GetFileFingerPrint(string filename)
        {
            Log.DebugFormat("Trying to get cached file finger print for '{0}'", filename);

            //First, try to get the value from the cache.
            object ret = HttpRuntime.Cache.Get(filename);
            if (ret != null)
            {
                //We got the value from the cache.
                Log.DebugFormat("Got cached file finger print for '{0}'", filename);
                return ((Task<AdsFileInfo>)ret).Result;
            }

            //Value doesn't exist in cache, create a Task object that can check the DB for it
            var task = new Task<AdsFileInfo>(() => ComputeFileFingerPrint(filename));

            //Try to add the task to the cache. If another thread managed to create and insert it before this thread,
            //we'll fail to add it, but we will get the other task's return value.
            ret = HttpRuntime.Cache.Add(filename, task, null,
                                        DateTime.UtcNow.AddSeconds(Global.Settings.FileFingerPrintCacheDuration),
                                        Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
            if (ret == null)
            {
                //Successfully added to cache, meaning there wasn't a task there before 
                task.Start();
                return task.Result;
            }

            Debug.Assert(ret is Task<AdsFileInfo>,
                         "(method GetFileFingerPrint) Cached object was supposed to be of type Task<string>");
            return ((Task<AdsFileInfo>)ret).Result;
        }

* This source code was highlighted with Source Code Highlighter.
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

A good basic step-by-step tutorial about Ninject

I hope this link stays up: http://tekpub.com/view/concepts/1

This video explains in a very clear way, how to use Ninject and what IoC (inversion of control) and DI (dependency injection) are. Recommended for anyone who doesn't know anything about those (yet). I wish I'd have found the video back when I was first trying to lace up Ninject into my code. Would have saved me some time, it's faster to understand than the guide Ninject has.Though very similar, it just is clearer and quicker to grasp.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

So, "don't use Singleton" ?

So I've read "Singleton I love you, but you're bringing me down" at http://www.codingwithoutcomments.com/ and the articles it refers to. And it makes sense, basically.

In my latest code, I created one Singleton (see http://geekswithblogs.net/AngelEyes/archive/2011/07/21/code-worth-remembering-singleton-implemented-in-c-4.0.aspx ) and had it hold the reference to my global factory, which, I guess, makes it a service locator. The factory itself uses (and hides from the rest of the code) Ninject 2.0. As long as that will stay the only Singleton, and hold no state other than the Kernel, then I'm safe :)

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Code worth remembering: Singleton implemented in C# 4.0

*Make sure you read Don't Use Singleton before using a Singleton at all...


Go read the whole post at http://geekswithblogs.net/BlackRabbitCoder/archive/2010/05/19/c-system.lazylttgt-and-the-singleton-design-pattern.aspx

   1: public class LazySingleton3
   2: {
   3:     // static holder for instance, need to use lambda to construct since constructor private
   4:     private static readonly Lazy<LazySingleton3> _instance
   5:         = new Lazy<LazySingleton3>(() => new LazySingleton3());
   6:  
   7:     // private to prevent direct instantiation.
   8:     private LazySingleton3()
   9:     {
  10:     }
  11:  
  12:     // accessor for instance
  13:     public static LazySingleton3 Instance
  14:     {
  15:         get
  16:         {
  17:             return _instance.Value;
  18:         }
  19:     }
  20: }
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Monads

Functional programming and Monads are a bit complex, and took me a while to understand. Surely, they're very different than OOP. So, I'd like to recommend Mike's World-O-Programming's "Yet Another Monad Tutorial"  (http://mvanier.livejournal.com/3917.html) as one of the best explanations for Monads. The step-by-step approach allows the reader to decide where to skip because "it's clear as water", and where to re-read and digest very slowly the harder parts. And maybe each person finds a different part hard.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Rename Applications and Virtual Directories in IIS7

from http://lanitdev.wordpress.com/2010/09/02/rename-applications-and-virtual-directories-in-iis7/

 

Rename Applications and Virtual Directories in IIS7

Have you ever wondered why the box to change the name or “Alias” on an application or virtual directory is greyed out (see screenshot below)? I found a way to change the name without recreating all your settings. It uses the built in administration commands in IIS7, called appcmd.

Renaming Applications In IIS7

  1. Open a command prompt to see all of your applications.
    1 C:> %systemroot%\system32\inetsrv\appcmd list app
    2  
    3     APP "Default Web Site/OldApplicationName"
    4     APP "Default Web Site/AnotherApplication"
  2. Run a command like this to change your “OldApplicationName” path to “NewApplicationName”. Now you can use http://localhost/newapplicationname
    1 C:> %systemroot%\system32\inetsrv\appcmd set app "Default Web Site/OldApplicationName" -path:/NewApplicationName
    2  
    3     APP object "Default Web Site/OldApplicationName" changed

Renaming Virtual Directories In IIS7

  1. Open a command prompt to see all of your virtual directories.
    1 C:> %systemroot%\system32\inetsrv\appcmd list vdir
    2  
    3     VDIR "Default Web Site/OldApplicationName/Images" (physicalPath:\\server\images)
    4     VDIR "Default Web Site/OldApplicationName/Data/Config" (physicalPath:\\server\config)

    We want to rename /Images to /Images2 and /Data/Config to /Data/Config2. Here are the example commands:

    1 C:> %systemroot%\system32\inetsrv\appcmd set vdir "Default Web Site/OldApplicationName/Images" -path:/Images2
    2  
    3     VDIR object "Default Web Site/OldApplicationName/Images" changed
    4  
    5 C:> %systemroot%\system32\inetsrv\appcmd set vdir "Default Web Site/OldApplicationName/Data/Config" -path:/Data/Config2
    6  
    7     VDIR object "Default Web Site/OldApplicationName/Data/Config" changed
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

WCF REST on .Net 4.0

 

A simple and straight forward article taken from http://christopherdeweese.com/blog2/post/drop-the-soap-wcf-rest-and-pretty-uris-in-net-4 which uses WCF REST Service Template 40(CS) 



Drop the Soap: WCF, REST, and Pretty URIs in .NET 4
Years ago I was working in libraries when the Web 2.0 revolution began.  One of the things that caught my attention about early start-ups using the AJAX/REST/Web 2.0 model was how nice the URIs were for their applications.  Those were my first impressions of REST; pretty URIs.  Turns out there is a little more to it than that.

REST is an architectural style that focuses on resources and structured ways to access those resources via the web.  REST evolved as an “anti-SOAP” movement, driven by developers who did not want to deal with all the complexity SOAP introduces (which is al lot when you don’t have frameworks hiding it all).  One of the biggest benefits to REST is that browsers can talk to rest services directly because REST works using URIs, QueryStrings, Cookies, SSL, and all those HTTP verbs that we don’t have to think about anymore.

If you are familiar with ASP.NET MVC then you have been exposed to rest at some level.  MVC is relies heavily on routing to generate consistent and clean URIs.  REST for WCF gives you the same type of feel for your services.  Let’s dive in.

WCF REST in .NET 3.5 SP1 and .NET 4
This post will cover WCF REST in .NET 4 which drew heavily from the REST Starter Kit and community feedback.  There is basic REST support in .NET 3.5 SP1 and you can also grab the REST Starter Kit to enable some of the features you’ll find in .NET 4.

This post will cover REST in .NET 4 and Visual Studio 2010.

Getting Started
To get started we’ll create a basic WCF Rest Service Application using the new on-line templates option in VS 2010:



When you first install a template you are prompted with this dialog:



Dude Where’s my .Svc File?
The WCF REST template shows us the new way we can simply build services.  Before we talk about what’s there, let’s look at what is not there:

The .Svc File
An Interface Contract
Dozens of lines of configuration that you have to change to make your service work
REST in .NET 4 is greatly simplified and leverages the Web Routing capabilities used in ASP.NET MVC and other parts of the web frameworks.  With REST in .NET 4 you use a global.asax to set the route to your service using the new ServiceRoute class.  From there, the WCF runtime handles dispatching service calls to the methods based on the Uri Templates.

global.asax

using System;
using System.ServiceModel.Activation;
using System.Web;
using System.Web.Routing;

namespace Blog.WcfRest.TimeService
{
    public class Global : HttpApplication
    {
        void Application_Start(object sender, EventArgs e)
        {
            RegisterRoutes();
        }

        private static void RegisterRoutes()
        {
            RouteTable.Routes.Add(new ServiceRoute("TimeService",
                new WebServiceHostFactory(), typeof(TimeService)));
        }
    }
}

The web.config contains some new structures to support a configuration free deployment.  Note that this is the default config generated with the template.  I did not make any changes to web.config.

web.config

<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule,
           System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </modules>
  </system.webServer>

  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    <standardEndpoints>
      <webHttpEndpoint>
        <!--
            Configure the WCF REST service base address via the global.asax.cs file and the default endpoint
            via the attributes on the <standardEndpoint> element below
        -->
        <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
      </webHttpEndpoint>
    </standardEndpoints>
  </system.serviceModel>

</configuration>


Building the Time Service
We’ll create a simple “TimeService” that will return the current time.  Let’s start with the following code:

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;

namespace Blog.WcfRest.TimeService
{
    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class TimeService
    {
        [WebGet(UriTemplate = "CurrentTime")]
        public string CurrentTime()
        {
            return DateTime.Now.ToString();
        }
    }
}
The endpoint for this service will be http://[machinename]:[port]/TimeService.  To get the current time http://[machinename]:[port]/TimeService/CurrentTime will do the trick.

The Results Are In


Remember That Route In global.asax?
Turns out it is pretty important.  When you set the route name, that defines the resource name starting after the host portion of the Uri.



Help Pages in WCF 4
Another feature that came from the starter kit are the help pages.  To access the help pages simply append Help to the end of the service’s base Uri.





Dropping the Soap
Having dabbled with REST in the past and after using Soap for the last few years, the WCF 4 REST support is certainly refreshing.  I’m currently working on some REST implementations in .NET 3.5 and VS 2008 and am looking forward to working on REST in .NET 4 and VS 2010.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

A quick (and elegant, IMHO) way to convert a byte array to hexadecimal string

        public static string ByteArrayToString(byte[] bytes)

        {

            return String.Join(string.Empty, Array.ConvertAll(bytes, x => x.ToString("X2")));

        }

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

How to: group by month with SQL

I took this particular code from http://weblogs.sqlteam.com/jeffs/archive/2007/09/10/group-by-month-sql.aspx,

a good read. Shows you what to avoid and why.

 

The recommended technique is the following:

 

GROUP BY dateadd(month, datediff(month, 0, SomeDate),0)

 

By the way, in the "select" clause, you can use the following:

 

SELECT

        month(dateadd(month, datediff(month, 0, SomeDate),0)) as [month],

        year(dateadd(month, datediff(month, 0, SomeDate),0)) as [year],

 

Just remember to also sort properly if needed:

 

ORDER BY dateadd(month, datediff(month, 0, SomeDate),0)

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

A batch files that opens windows explorer windows

Use this when you need to open multiple windows on a regular bassis, such as when deploying manually.


%SystemRoot%\explorer.exe "D:\dev\Trunk\web\Mysite\PrecompiledWeb"

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

How to: Check which table is the biggest, in SQL Server

The company I work with had it's DB double its size lately, so I needed to find out which tables were the biggest.

I found this on the web, and decided it's worth remembering!

Taken from http://www.sqlteam.com/article/finding-the-biggest-tables-in-a-database, the code is from http://www.sqlteam.com/downloads/BigTables.sql

 

/**************************************************************************************
*
*  BigTables.sql
*  Bill Graziano (SQLTeam.com)
*  graz@sqlteam.com
*  v1.1
*
**************************************************************************************/

DECLARE @id INT
DECLARE @type CHARACTER(2)
DECLARE @pages INT
DECLARE @dbname SYSNAME
DECLARE @dbsize DEC(15, 0)
DECLARE @bytesperpage DEC(15, 0)
DECLARE @pagesperMB DEC(15, 0)

CREATE TABLE #spt_space
  (
     objid    INT NULL,
     ROWS     INT NULL,
     reserved DEC(15) NULL,
     data     DEC(15) NULL,
     indexp   DEC(15) NULL,
     unused   DEC(15) NULL
  )

SET nocount ON

-- Create a cursor to loop through the user tables
DECLARE c_tables CURSOR FOR
  SELECT id
  FROM   sysobjects
  WHERE  xtype = 'U'

OPEN c_tables

FETCH NEXT FROM c_tables INTO @id

WHILE @@FETCH_STATUS = 0
  BEGIN
      /* Code from sp_spaceused */
      INSERT INTO #spt_space
                  (objid,
                   reserved)
      SELECT objid = @id,
             SUM(reserved)
      FROM   sysindexes
      WHERE  indid IN ( 0, 1, 255 )
             AND id = @id

      SELECT @pages = SUM(dpages)
      FROM   sysindexes
      WHERE  indid < 2
             AND id = @id

      SELECT @pages = @pages + Isnull(SUM(used), 0)
      FROM   sysindexes
      WHERE  indid = 255
             AND id = @id

      UPDATE #spt_space
      SET    data = @pages
      WHERE  objid = @id

      /* index: sum(used) where indid in (0, 1, 255) - data */
      UPDATE #spt_space
      SET    indexp = (SELECT SUM(used)
                       FROM   sysindexes
                       WHERE  indid IN ( 0, 1, 255 )
                              AND id = @id) - data
      WHERE  objid = @id

      /* unused: sum(reserved) - sum(used) where indid in (0, 1, 255) */
      UPDATE #spt_space
      SET    unused = reserved - (SELECT SUM(used)
                                  FROM   sysindexes
                                  WHERE  indid IN ( 0, 1, 255 )
                                         AND id = @id)
      WHERE  objid = @id

      UPDATE #spt_space
      SET    ROWS = i.ROWS
      FROM   sysindexes i
      WHERE  i.indid < 2
             AND i.id = @id
             AND objid = @id

      FETCH NEXT FROM c_tables INTO @id
  END

SELECT TOP 25 table_name = (SELECT LEFT(name, 25)
                            FROM   sysobjects
                            WHERE  id = objid),
              ROWS = CONVERT(CHAR(11), ROWS),
              reserved_kb = Ltrim(Str(reserved * d.low / 1024., 15, 0) + ' ' + 'KB'),
              data_kb = Ltrim(Str(data * d.low / 1024., 15, 0) + ' ' + 'KB'),
              index_size_kb = Ltrim(Str(indexp * d.low / 1024., 15, 0) + ' ' + 'KB'),
              unused_kb = Ltrim(Str(unused * d.low / 1024., 15, 0) + ' ' + 'KB')
FROM   #spt_space,
       MASTER.dbo.spt_values d
WHERE  d.NUMBER = 1
       AND d.TYPE = 'E'
ORDER  BY reserved DESC

DROP TABLE #spt_space

CLOSE c_tables

DEALLOCATE c_tables 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Kill connections to resote DB - SQL Server

The following code is from Ralph Whitbeck's blog. This is really a "cut and save" for me :)

When restoring an SQL Server Database, you'll often need to kill existing connections to it, before starting the task.

Change databaseName To the actual database name.

Use Master
Go

Declare @dbname sysname

Set @dbname = 'databaseName'

Declare @spid int
Select @spid = min(spid) from master.dbo.sysprocesses
where dbid = db_id(@dbname)
While @spid Is Not Null
Begin
        Execute ('Kill ' + @spid)
        Select @spid = min(spid) from master.dbo.sysprocesses
        where dbid = db_id(@dbname) and spid > @spid
End

 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

CustomValidator OnServerValidate not Firing

I ran into a problem where the CustomValidator OnServerValidate not Firing.

After a lot of trial-and-error checking, I found out, the problem was that it didn't tolerate the yellow brackets. No errors were thrown, which was very frustrating.

This is what didn't work, to make it work, all i had to do was move the error to the code-behind:

<asp:CustomValidator ID="DiscountCouponCodeValidator" runat="server"

ErrorMessage="<div class='blizz-form-field-row-err' style='padding:0 25px;width:325px;margin-left:20px;margin-top:-15'><%# RM.GetString("VALID_COUPON_ERROR") %>" OnServerValidate="ValidateCoupon"></asp:CustomValidator>

 


 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

SQL Server , How to search for text in Stored Procedures

In this example, I searched for any SP containing the text LoadByIP:


 

SELECT Distinct SO.Name

FROM sysobjects SO (NOLOCK)

INNER JOIN syscomments SC (NOLOCK) on SO.Id = SC.ID

AND SO.Type = 'P'

AND SC.Text LIKE '%LoadByIP%'

ORDER BY SO.Name

 

 

Update: this was suggested by nts (see comments):

 

SELECT routine_name, routine_definition

FROM information_schema.routines

WHERE routine_definition LIKE '%LoadByIP%'

AND routine_type = 'PROCEDURE'

Both work well :-)

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Regular expression for inverting "let" statements.

This regular expression isn't  standard, it's Visual Studio syntax-specific, it should invert simple statements such as:

     Language.Text = record.Language;
into
     record.Language=            Language.Text ;


The expression itself is: ^{.+}={.+};
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

A simple custom control, inheriting from BoundField

I wanted to display Boolean data in a Gridview and didn't like that disabled checkbox look. After searching online, I found some people solved this with Javascript, including the MS AJAX extentions toolkit which has an extender - but I didn't want to have a lot of checkboxes in my html that got replaced on the client's side with javascript that had to loop over them all. I just wanted the images.

The quick-and-dirty way to solve this would have been to create a template column for my Gridview with an image control in it and override the Grid's data binding method to set the ImageUrl property.

But that would have to be done everytime, for every Gridview I'd want to use.

So I wrote a simple custom control, inheriting from BoundField (System.Web.UI.WebControls.BoundField) and now I can use it in any website, in any Gridview.

I liked it - hope you do too.

using System;
using System.Data;

using System.Configuration;

using System.Web;

using System.ComponentModel;

using System.Web.UI;

using System.Web.UI.WebControls;

 

namespace CustomBoundField

{
    ///<summary>

    /// Summary description for BoundCheckImageField

    ///</summary>
    public class BoundCheckImageField : System.Web.UI.WebControls.BoundField
    {
        #region Properties
 

        ///<summary>

        /// Gets or sets the url of the image to display for a 'true' value

        ///</summary>

        [DefaultValue("")]

        public string TrueValueImageUrl

        {

            get

            {

                object val = base.ViewState["TrueValueImageUrl"];

                if (val != null)

                {

                    return (string)val;

                }

                return string.Empty;

            }

            set

            {

                if (!object.Equals(value, base.ViewState["TrueValueImageUrl"]))

                {
                    base.ViewState["TrueValueImageUrl"] = value;
                    this.OnFieldChanged();
                }

            }

        }

 

        ///<summary>

        /// Gets or sets the url of the image to display for a 'false' value

        ///</summary>

        [DefaultValue("")]

        public string FalseValueImageUrl

        {

            get

            {

                object val = base.ViewState["FalseValueImageUrl"];

                if (val != null)

                {

                    return (string)val;

                }

                return string.Empty;

            }

            set

            {

                if (!object.Equals(value, base.ViewState["FalseValueImageUrl"]))

                {
                    base.ViewState["FalseValueImageUrl"] = value;
                    this.OnFieldChanged();
                }

            }

        }

 
        #endregion
 

        protected override void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState)

        {

            //base.InitializeDataCell(cell, rowState);

 

            if (!string.IsNullOrEmpty(this.DataField))

            {

                Image img = new Image();

                img.DataBinding += new EventHandler(this.OnImageDataBind);
                cell.Controls.Add(img);

            }

        }

 

        protected void OnImageDataBind(object sender, EventArgs e)

        {

       

            Control control = (Control)sender;

            Control namingContainer = control.NamingContainer;

            object dataValue = this.GetValue(namingContainer);

 

            if (control is Image)

            {

                if ((Boolean)dataValue)

                {

                    (control as Image).ImageUrl = this.TrueValueImageUrl;

                }
                else
                {

                    (control as Image).ImageUrl = this.FalseValueImageUrl;

                }

            }

            else

            {

                base.OnDataBindField(sender, e);

            }

        }

    }
}
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

keyboard shortcut collapse all nodes in the Solution Explorer

How to quickly collapse all nodes in the Solution Explorer (To my knowledge, this works with Visual Studio 2005 as well as Visual Studio 2008):




1. Create a macro (code taken from Jay Harris's blog. Update: I cannot find that post anymore. Good thing I copied it here!)

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics

Public Module CollapseAll
    Sub CollapseAll()
        ' Get the the Solution Explorer tree 
        Dim UIHSolutionExplorer As UIHierarchy
        UIHSolutionExplorer = DTE.Windows.Item(Constants.vsext_wk_SProjectWindow).Object()
        ' Check if there is any open solution 
        If (UIHSolutionExplorer.UIHierarchyItems.Count = 0) Then
            ' MsgBox("Nothing to collapse. You must have an open solution.") 
            Return
        End If
        ' Get the top node (the name of the solution) 
        Dim UIHSolutionRootNode As UIHierarchyItem
        UIHSolutionRootNode = UIHSolutionExplorer.UIHierarchyItems.Item(1)
        UIHSolutionExplorer = Nothing
        UIHSolutionRootNode.DTE.SuppressUI = True
        ' Collapse each project node 
        Dim UIHItem As UIHierarchyItem
        For Each UIHItem In UIHSolutionRootNode.UIHierarchyItems
            'UIHItem.UIHierarchyItems.Expanded = False 
            If UIHItem.UIHierarchyItems.Expanded Then
                Collapse(UIHItem)
            End If
        Next
        ' Select the solution node, or else when you click 
        ' on the solution window 
        ' scrollbar, it will synchronize the open document 
        ' with the tree and pop 
        ' out the corresponding node which is probably not what you want. 
        UIHSolutionRootNode.Select(vsUISelectionType.vsUISelectionTypeSelect)
        UIHSolutionRootNode.DTE.SuppressUI = False
        UIHSolutionRootNode = Nothing
    End Sub

    Private Sub Collapse(ByVal item As UIHierarchyItem)
        For Each eitem As UIHierarchyItem In item.UIHierarchyItems
            If eitem.UIHierarchyItems.Expanded AndAlso eitem.UIHierarchyItems.Count > 0 Then
                Collapse(eitem)
            End If
        Next
        item.UIHierarchyItems.Expanded = False
    End Sub

End Module


2.  As shown here, create a new keyboard shortcut for your new macro:
•    Choose Tools/Options and select Environment/Keyboard.
•    Type in something into "Show commands containing" to get a list of matching commands. If there is already a shortcut for the selected command, it’ll be displayed in "Shortcuts for selected command".
•    To assign a new shortcut to the selected command, put the cursor in "Press shortcut keys" and press the shortcut key or key combinations desired.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Setting up Right-to-Left menu, with ASP .Net CSS friendly control adapters

A great article, albeit in Hebrew, explains How to align RTL (Right-to-left) ASP.Net 2.0 Menu with CSS Control Adapters.

Note, in particular, this change:
  /* Tier 3+ */
.SimpleEntertainmentMenu ul.AspNet-Menu ul ul
{
    top: -0.5em;   
    left: 6em;
}

Changed to:

  /* Tier 3+ */
.SimpleEntertainmentMenu ul.AspNet-Menu ul ul
{
    top: -0.5em;   
    right: 6em;
}

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Manually postback

I wanted to post back after an auto complete extender did its job. This was the first version (the auto complete extender showed student names).

Server-side:

    protected override void OnPreRender(EventArgs e)

    {

        base.OnPreRender(e);

        if (!Page.ClientScript.IsClientScriptBlockRegistered("postBackStudentFound"))

        {

            Page.ClientScript.RegisterClientScriptBlock(this.Page.GetType(), "postBackStudentFound",

                @"<script type=""text/javascript"">function postBackStudentFound() {" +

                 Page.ClientScript.GetPostBackEventReference(this.Page, StudentFoundEventArg) + "; } </script>");

        }

        if (Page.IsPostBack)

        {

            if (Request["__EVENTARGUMENT"] == StudentFoundEventArg)

            {

                OnStudentFound();

            }

        }

    }

Client-side:

<script type="text/javascript">

function itemSelected( source, eventArgs)

{
    var fullString = eventArgs.get_value();
    var valuesArray = fullString.split("|");
    var id = valuesArray[0];
    var key = valuesArray[2];

    $get('<%= txtID.ClientID %>').value = id;  

    postBackStudentFound();

}
</script>

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Example: how to sort and get top iNumOfRecords from a DataTable, using a DataView

DataView dvSortTotalUpdates = new DataView();

dvSortTotalUpdates = dtAllUpdates.DefaultView;

dvSortTotalUpdates.Sort = "UploadDate";

DataTable dtGetBySize = dtAllUpdates.Clone();

for( int i = 0; i < iNumOfRecords; i++ )

{

dtGetBySize.ImportRow(dvSortTotalUpdates[i].Row);

}

 

return (dtGetBySize);

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Using a MemoryStream with GZipStream

This is a very subtle yet annoying bug. And it's hard to find.
Fortunately, I found help on the BCL Team Blog.

Just in case (I've had posts that I linked to disappear in the past) I'll copy here what they say:

We’ve seen cases where our customers have run into issues when using a MemoryStream with GZip compression. The problem can be frustrating to debug and I thought I’ll blog about it in the hope that others would avoid a similar issue. The code for this looks like this;



Byte[] compressedBuffer;

MemoryStream stream = new MemoryStream();

using (GZipStream zip = new GZipStream(stream, CompressionMode.Compress))

{

//compress data

...



//Dont get the MemoryStream data before the GZipStream is closed since it doesn’t yet contain complete compressed data.

//GZipStream writes additional data including footer information when its been disposed

compressedBuffer = stream.ToArray(); //WRONG

}

// CORRECT CODE: call compressedBuffer = stream.ToArray() here after the GZipStream is disposed



The problem arises because the data in MemoryStream is not complete when ToArray is called before the GZipStream is closed. We will write any remaining compressed data and footer information to GZipStream when its being closed. The data in the MemoryStream is still accessible even after its been closed. Both ToArray and GetBuffer methods will return valid data after the MemoryStream has being disposed. This is not so much an issue when another stream like FileStream is used in compression since there is generally time before decompression when a file is used and its ok for the file to be re-opened when that happens.
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

SQL Server aggregated report example

An example of how to make an aggregated report, grouping together by values:


    select  count(*) as total ,
        count(case WHEN others = 1 THEN 1 END)    as [one url],
        count(case WHEN others = 2 THEN 1 END)    as [two urls],
        count(case WHEN others = 3 THEN 1 END)    as [three urls],
        count(case WHEN others > 3 THEN 1 END)    as [all the rest]
        from #temp2
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati
«February»
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
26272829123
45678910