WebMasterSam

.Net, SEO, Dynamics CRM, AdSense/AdWords, Dating sites, Silverlight, Web hosting and more
PPC management, Online Marketing, Search Marketing, SEO, Website development - dotmedias.com

About me

I'm an IT consultant working primarily with the .Net Framework as a developper and architect. I also work on my own on my personnal dating websites. I've been developping websites since 2000.

If you like what I do, feel free to support me

PayPal - The safer, easier way to pay online!

Bookmark

Bookmark and Share

Sponsored links

Amazon hot deals

Computer releases

Last comments

None

Adding custom error message to ValidationSummary without validators

Validators are a great thing in the ASP.Net world (as well as the .Net WinForms world...), but sometimes they don't suffice. For example, if you want to validate something not related to a control on the page or something very complex you can't achieve even with the custom validators, you may want a particular solution like this one.

First approach : using the CustomValidator

With this approach you simply have to do the following piece of code when you want to add a custom message to your validator :


CustomValidator val = new CustomValidator();

val.IsValid = false;
val.ErrorMessage = "Custom error message to add to the ValidationSummary";

this.Page.Validators.Add(val);

This is a cool, clean and simple way to add custom error messages to the ValidationSummary.

Second approach : creating a validator by implementing IValidator

The .Net framework allows you to create very custom validator by implementing the IValidator interface. So you create the validator and then use the same technique I've just showed you before, just like this :


public class ValidationError : IValidator
{
    private ValidationError(string message)
    {
        this.ErrorMessage = message;
    }

    public void Validate()
    {
        this.IsValid = false;
    }
}

this.Page.Validators.Add(new ValidationError("Your custom error message"));

Personnaly I prefer this one because you are completely custom and you can add messages in a single line of code.

Posted: Jul 03 2009, 15:15 by WebMasterSam | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: .Net | Programming
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us

I don't see ASP.Net 3.5 on IIS; only 2.0 is there

When you configure IIS, you have to tell it which version of ASP.Net you will be using for the website (or web application). Because you can run multiple versions of the framework on the same server, you have to select the correct version on a dropdown list, just like this :

When you install the framework 3.5 you can be surprised not to see it on the dropdown list.

Why do I don't see the .Net Framework 3.5 on IIS ?

You don't see the 3.5 because it is not a complete framework, it's only an "update" to the 2.0, so you only see 2.0. You will have the same exact behavior for the 3.0 framework as it is also an update to the 2.0 (prior to the 3.5).

If you take a look in C:/Windows/Microsoft.Net/Framework/3.5 you will not see as much stuff as you normally see on the 2.0 folder. For example, if you want to run aspnet_regiis for the .Net framework 3.5 you will not find the tool because the 3.5 is the 2.0 in fact, so you will have to run the aspnet_regiis tool for the 2.0 framework.

What about the 4.0 framework ?

This is a different relaity for the .Net framework 4.0 because it's a complete new framework, not only an update to the 2.0 so in IIS you will see an option in the list for the version 4.0 of the framework.

Posted: Jul 03 2009, 14:36 by WebMasterSam | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: .Net
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us

ASP.Net MachineKey generator

When you setup a server involving ASP.Net, you need (if you want to be clean) to set the machineKey. When I do this I always type the same thing on Google : "MachineKey generator". I decided to list some of them I often use :

ASP.Net resources machineKey generator

Pete's Nifty MachineKey generator

OrcsWeb machineKey generator

Posted: Jul 03 2009, 14:26 by WebMasterSam | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: .Net
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us

Culture ID 2155 (0x086B) is not a supported culture

I recently came across a VERY annoying problem on my personnal (this one) BlogEngine.Net blog.

What happened is that I installed some Windows Updates (a bunch) on my Windows Server 2003 server and then, every time I accessed an article of this blog I received this error message : Culture ID 2155 (0x086B) is not a supported culture. What a real annoying problem !!

I don't know the exact reason but what I know is that cultures are OS specific, so the Windows Update is the cause... it's not related to the .Net Framework so don't waste your time trying to reinstall the framework, it will not work.

The Solution...

Resintall the Service Pack 2 for your Windows Server 2003.

TreeNode bolded text gets cropped (clipped) in the .Net TreeView

If you use the TreeView that comes with the .Net Framework, you probably hit the following problem :

You add bold elements because you want some formatting, and what you see is that your bolded elements gets cropped. You try to set the NodeFont before and after setting the text of the node but nothing seem to make a change, so you decide to Google this and find this MSDN article (TreeNode.NodeFont property) that says in a note, "If the node font is larger than the Font property value set in the TreeView control, the tree node label text is clipped".

So what to do ? Simple solution !

You set the NodeFont property of the TreeView to a bolded font and then, when you add your nodes to your TreeView, you set the NodeFont property (of the nodes) to a non-bolded font (except for the bolded elements). You will then see what you expected :

Posted: Jun 02 2009, 12:33 by WebMasterSam | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: .Net | Programming
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us

Rent a coder; does this really work ?

If you're a programmer, you certainly already created a little program or website for someone and get paid for it. This is a normal thing; you have a talent that some others don't have and you can help them, charging something for your time and effort.

On the web, there is this kind of thing too. You can pay someone for a specifig job you want to be done. There is websites that exposes this principle like RentACoder and GetACoder. These websites look great, there is a lot of projects awaiting for bids and plenty of coders ready to code ! Fine, this seems to be a great place to search for custom jobs or to post a project you don't the time (or knowledge) to do by yourself.

So, let's take a look to both sides of the medal...

Being a coder, bidding on projects

When you signup on websites like RentACoder, you can search for projects you want to realize. There is plenty of different categories: .Net, Java, SQL Server, MySQL, graphic design, bug fixing, etc... so you can find a perfect project for you and bid on.

Now that you've found the project you start to bid on and you think about a price (between the price range). You than have your price in mind but you find that 50 indians have already bidded on this for 10% of the price you thought of charging... Damn ! This is the reality, in india, being paid 5$/hour is big. Here, if we work as a freelancer we can easily charge 40$-100$ per hour. Every single project you will find will have indian bids on it. Maybe the project manager don't want cheap indian code for a fraction of the price, but wants someone who will charge a lot more but do a great job so with those projects, you may have a chance on winning it.

If you win the project, you will have to realize it so you will need specifications, you will need to talk to the project manager often to really understand his needs. This can be hard. Remember what you do at your day job... you're near from the client, you ask questions anytime, you do meetings, you chat, etc... The communication is easy, but if the client is about 1000km away, will you spend hours on phone ? Paying bills will kill all the profit you can make out of the project itself. Will you chat everyday ? Chatting is good for easy questions, but don't make serious decisions using MSN. Will you have the opportunity to meet up with the project manager ? Maybe not if he lives far from you, and I'm sure no one of you will pay 200$ for a plane ticket on a 400$ project !

There is also another thing that may scares some people... will you really get paid for you work ? When you give your source code, the project manager can stop talking to you, stole your work and don't pay a dime for it... it's a danger. I don't know if this happens often but, it's not risk-free.

Being a project manager, awaiting for bids

Being a project manager is not very different from being a coder because the real problem with coder rental is the communication, and this is a problem for both sides. Even if this problem is the same, there is some other things that are different... Like I said previously, there is a lot of indians that want to work for peanuts so you will be able to buy something that fits your needs for a small amount of money.

So you decide to take someone for your project (whoever he his and where he's from). You send him the specifications of the work to be done and he starts to work on it. You communicate everyday to have a feedback about the way the developpment is going... eveything seems to be fine.

Then, you get your work, you pay for it and do what you have to do with your project (put it on the internet, use it on your intranet, etc...). Everything seems to be fine but soon you discover some bugs and you open the code... What you find is not, and absolutely not following any existing programming best practices. You're not able to follow the code logic (if there is a logic...), you find weird things and... Damn it ! You can maintain this code without rewriting a big part... This is normal, you can't control someone else's code. Personnaly at my day job I check my coworkers code barely every day and find things that I tell them to change or fix it the best they can, but I will never be satisfied until I do it myself.

Conclusion...

Personnaly I think that you can't rent a coder... at least 90% of the time. I think sometimes you can rent someone to create graphical content or database design, but I don't think you can have success with programming. So in general, I don't think it's a good idea being a coder and not a good idea being a project manager (on rent a coder).

Posted: Apr 30 2009, 16:29 by WebMasterSam | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us

Be paid to fill surveys online; can we really make money with this ?

If you read this article it is because you are thinking about filling surveys online to make an extra cash every week. Like many other people, making money online is a thing we want to be able to do. If you think you can make money online, you're right, there IS a lot of ways to make money online, sitting at home and working only a few hours per day.

To day I will explain what is all about be paid to fill surveys online.

Is it hard to fill surveys and hard to find surveys to fill ?

Non, it's easy to fill, you only give your opinions about some products/services. You have offers everywhere on the internet, so you can find some good surveys only by surfing on your favorite sites. If you don't trust me, just spend about 5 minutes on facebook and you will see ads for "surveys money".

How much money can we make from this ?

It will depend on how much time you want to spend online filling surveys, but for sure, you will not become millionaire with this ! If you spend a few hours a week doing this you can make from 20$ to 100$ per week. You can make more than this but it general it will look like this. It always depends on current offers and the time you want to spend on it. I presonnaly don't know people who do 1000$ a week, even in a month.

Is it right or me ?

If you want something you can do every week (maybe everyday) because you're tired of spending your time on useless websites playing online little flash game or reading jokes or whatever you do to spend your time on your computer, this can be a little sideline. You will spend time, and be paid to spend it.

On the other hand, if for you time is money, don't fill surveys online, you'll lose your time. At the begginning you will say "Wow ! it's very easy to make money with this, I will do this all weekends and every evening when I comeback home from a day of work", but 3 or 4 days after you will say "Ahh damn it, I'm tired of filling these, I don't want this anymore".

Is it all legitimate or I can really lose my time with this ?

Like any other thing on the internet, you can be fooled if you trust anything you see. There is a lot more scams in online paid surveys than legitimate one so don't be surprised if one day you don't receive your paycheck of even worse, if you get frauded.

Conclusion...

Personnaly, I think that online paid surveys are only for a small audience and whoever you are you should think about starting to fill surveys online to make money. You can lose more time than money you can get.

Posted: Apr 30 2009, 15:38 by WebMasterSam | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: Misc | Make money online
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us

What is a .XAP file (SilverLight) and what does it contain

If you already created a Silverlight application you have certainly noticed that all you do in your Silverlight project will be packaged as a XAP file that you will then put on your website.

What is a XAP file ?

The XAP file is a package that contains everything your Silverlight application needs to run on the client browser.

What does it contain ?

All the assemblies (DLL) you created, all the Framework assemblies you referenced in your application (like System.Xml.Linq, System.Windows.Controls and some others) and a manifest file, named AppManifest.xaml. It also contains culture-specific assemblies (if you translated your application in some other languages).

What does XAP stands for ?

You have to pronounce "ZAP" and it stands for "Silverlight Application Package". I don't know why MS didn't called it SAP instead of XAP but... this is it's meaning !

Can I open a XAP file ?

Oh sure you can, it's only a ZIP file. You can rename it an open it with WinRar or WinZip.

How can I create a XAP file ?

You build your Silverlight project ! Simple, no ?

Why does my Silverlight application is packaged in a XAP file ?

There's 3 main reasons for this :

  1. Because all the content can be compressed within the zip file so you save bandwith and time
  2. Because DLLs are prohibited from downloading (by default)
  3. Because it's easier to download one file than "72" (any number) files
What does the AppManifest.xaml looks like ?

This file is the main entry point in the package for the Silverlight client. When Silverlight extracts the content of the XAP package it reads the AppManifest.xaml to know which assembly it has to load.


<Deployment EntryPointAssembly="SilverlightApplication1">
  <Deployment.Parts>
    <AssemblyPart x:Name="SilverlightApplication1" Source="SilverlightApplication1.dll" />
    <AssemblyPart x:Name="Silverlight.Trace" Source="Silverlight.Trace.dll" />
    <AssemblyPart x:Name="System.Windows.Controls" Source="System.Windows.Controls.dll" />
    <AssemblyPart x:Name="System.Xml.Linq" Source="System.Xml.Linq.dll" />
    <AssemblyPart Source="en/SilverlightApplication1.resources.dll" />
    <AssemblyPart Source="fr/SilverlightApplication1.resources.dll" />
    <AssemblyPart Source="fr/System.Xml.Linq.resources.dll" />
    <AssemblyPart Source="fr/System.Windows.Controls.resources.dll" />
  </Deployment.Parts>
</Deployment>

How do I use a XAP file ?

You ? You don't use this file; Silverlight does. The only thing you have to do with it is copy it to your ASP.Net application.

Where do I deploy my XAP file ?

If you want to do it the common way, deploy it to the ClientBin folder. You can deploy it wherever you want but, I suggest you put it in the ClientBin folder.

Complete .Net COM+ interop class (COMAdmin wrapper)

If you already worked with the Interop.COMAdmin, you certainly said a lot of bad bad words ! Don't worry, you're not alone. Recently a friend of mine has to create an application that can export security from COM+ and then reimport it on another server. Because I love to do very technical code I decided to write a complete COM+ interop class that wraps the Interop.COMAdmin one. By doing this, my friend had a clean interop do deal with and so the tool to export security has been realized very quickly.

I decided to write a really clean interop so I spent about 3 days of work just to write this interop because no one on the internet has took the time to create it ! I want to share it with you because it can make you save a looooooooooot of time and frustration. You can download the code right here : ComPlusInterop.zip (31.45 kb).

The architecture behind that interop is as follow; there is a base class, COMElementBase, that wraps the access to the COMObject and there is derived classes matching the different things in COM+ such a applications, components, roles, methods and interfaces. Here is a list of the different classes the interop has :

  • ComponentServices
    • Represents the COM+ instance (can be from a remote server)
  • COMElementBase
    • The base class for the following classes
  • COMApplication
    • Represents an application
  • COMComponent
    • Represents a component (DLL)
  • COMInterface
    • Represents an interface of a component
  • COMMethod
    • Represents a method of an interface
  • COMRole
    • Represents a role definition
Because everything in COM+ is retrieved by string, I have a lot of constant values in each different class; each constant matches the internal property name. To retrieve a property value or to set one, the derived class (such as COMApplication) calls an internal method of the COMElementBase class. To simplify the process of casting property values, I created several methods in the base class to retrieve property values like GetPropertyValueBoolean, GetPropertyValueInteger and so on...

To show you in code what it looks like, here's the COMComponent class :


using Interop.COMAdmin;

using System.Runtime.InteropServices;

public class COMComponent : COMElementBase, IComparable
{
    #region "Members"

        private ReadOnlyCollection<COMInterface> _lstInterfaces;
        private ReadOnlyCollection<string> _lstRoles;
        private COMApplication _parent = null;

        private COMAdminCatalogCollection _colInterfaces = null;
        private COMAdminCatalogCollection _colRoles = null;

        private bool _dispose = false;

    #endregion

    #region "Constantss"

        internal const string NUMBER_ERROR_VERSION_INVALID = "0x8011042C";

        internal const string KEY_COLLECTION_INTERFACE = "InterfacesForComponent";
        internal const string KEY_COLLECTION_ROLES = "RolesForComponent";

        internal const string PROPERTY_NAME = "ProgID";
        internal const string PROPERTY_GUID = "CLSID";
        internal const string PROPERTY_DESCRIPTION = "Description";
        internal const string PROPERTY_DLL = "DLL";
        internal const string PROPERTY_MAJOR_VERSION = "VersionMajor";
        internal const string PROPERTY_MINOR_VERSION = "VersionMinor";
        internal const string PROPERTY_BUILD_VERSION = "VersionBuild";
        internal const string PROPERTY_SUBBUILD_VERSION = "VersionSubBuild";
        internal const string PROPERTY_TRANSACTION = "Transaction";
        internal const string PROPERTY_COMPONENT_TRANSACTION_TIMEOUT_ENABLED = "ComponentTransactionTimeoutEnabled";
        internal const string PROPERTY_COMPONENT_TRANSACTION_TIMEOUT = "ComponentTransactionTimeout";
        internal const string PROPERTY_ACCESS_CHECKS_ENABLED = "ComponentAccessChecksEnabled";
        internal const string PROPERTY_POOLING_ENABLED = "ObjectPoolingEnabled";
        internal const string PROPERTY_MAX_POOL_SIZE = "MaxPoolSize";
        internal const string PROPERTY_MIN_POOL_SIZE = "MinPoolSize";
        internal const string PROPERTY_CREATION_TIMEOUT = "CreationTimeout";
        internal const string PROPERTY_CONSTRUCTION_ENABLED = "ConstructionEnabled";
        internal const string PROPERTY_CONSTRUCTION_STRING = "ConstructorString";
        internal const string PROPERTY_JIT_ACTIVATION = "JustInTimeActivation";
        internal const string PROPERTY_EVENT_TRACKING_ENABLED = "EventTrackingEnabled";
        internal const string PROPERTY_MUST_RUN_IN_CLIENT_CONTEXT = "MustRunInClientContext";
        internal const string PROPERTY_MUST_RUN_IN_DEFAULT_CONTEXT = "MustRunInDefaultContext";
        internal const string PROPERTY_IS_PRIVATE = "IsPrivateComponent";
        internal const string PROPERTY_SYNCHRONIZATION = "Synchronization";
        internal const string PROPERTY_THREADING_MODEL = "ThreadingModel";
        internal const string PROPERTY_EXCEPTION_CLASS = "ExceptionClass";

    #endregion

    #region "CTOR"

        internal COMComponent(COMAdminCatalogObject COMobject, COMAdminCatalogCollection collection, COMApplication parent)
            : base(COMobject, collection)
        {


            _parent = parent;
        }

        protected override void Dispose(bool disposing)
        {

            base.Dispose(disposing);

            if (!_dispose)
            {

                if (_colInterfaces != null)
                {
                    Marshal.ReleaseComObject(_colInterfaces);
                }

                if (_colRoles != null)
                {
                    Marshal.ReleaseComObject(_colRoles);

                }
            }


            _dispose = true;
        }

    #endregion

    #region "Properties"

        public ReadOnlyCollection<COMInterface> Interfaces
        {
            get
            {

                if (_lstInterfaces == null)
                {
                    RetrieveInterfaces();
                }


                return _lstInterfaces;
            }
        }

        public ReadOnlyCollection<string> RolesCoches
        {
            get
            {

                if (_lstRoles == null)
                {
                    RetrieveRoles();
                }


                return _lstRoles;
            }
        }

        public string Name
        {
            get { return base.GetPropertyValueString(PROPERTY_NAME); }
        }

        public Guid ID
        {
            get { return base.GetPropertyValueGUID(PROPERTY_GUID); }
        }

        public string DLLPath
        {
            get { return base.GetPropertyValueString(PROPERTY_DLL); }
        }

        public string Version
        {
            get { return string.Format("{0}.{1}.{2}.{3}", base.GetPropertyValueInteger(PROPERTY_MAJOR_VERSION), base.GetPropertyValueInteger(PROPERTY_MINOR_VERSION), base.GetPropertyValueInteger(PROPERTY_BUILD_VERSION), base.GetPropertyValueInteger(PROPERTY_SUBBUILD_VERSION)); }
        }

        public string Description
        {
            get { return base.GetPropertyValueString(PROPERTY_DESCRIPTION); }
            set { base.SetPropertyValue(PROPERTY_DESCRIPTION, value); }
        }
        public bool ComponentTransactionTimeoutEnabled
        {
            get { return base.GetPropertyValueBoolean(PROPERTY_COMPONENT_TRANSACTION_TIMEOUT_ENABLED); }
            set { base.SetPropertyValue(PROPERTY_COMPONENT_TRANSACTION_TIMEOUT_ENABLED, value); }
        }

        public int ComponentTransactionTimeout
        {
            get { return base.GetPropertyValueInteger(PROPERTY_COMPONENT_TRANSACTION_TIMEOUT); }
            set
            {
                if (value < 0 || value > 3600)
                {
                    throw new OverflowException("La valeur doit être comprise entre 0 et 3600.");
                }
                else
                {
                    base.SetPropertyValue(PROPERTY_COMPONENT_TRANSACTION_TIMEOUT, value);
                }
            }
        }

        public bool AccessChecksEnabled
        {
            get { return base.GetPropertyValueBoolean(PROPERTY_ACCESS_CHECKS_ENABLED); }
            set { base.SetPropertyValue(PROPERTY_ACCESS_CHECKS_ENABLED, value); }
        }

        public bool PoolingEnabled
        {
            get { return base.GetPropertyValueBoolean(PROPERTY_POOLING_ENABLED); }
            set { base.SetPropertyValue(PROPERTY_POOLING_ENABLED, value); }
        }

        public int MaxPoolSize
        {
            get { return base.GetPropertyValueInteger(PROPERTY_MAX_POOL_SIZE); }
            set
            {
                if (value < 1 || value > 1048576)
                {
                    throw new OverflowException("The value must be between 1 and 1048576.");
                }
                else
                {
                    base.SetPropertyValue(PROPERTY_MAX_POOL_SIZE, value);
                }
            }
        }

        public int MinPoolSize
        {
            get { return base.GetPropertyValueInteger(PROPERTY_MIN_POOL_SIZE); }
            set
            {
                if (value < 0 || value > 1048576)
                {
                    throw new OverflowException("The value must be between 0 and 1048576.");
                }
                else
                {
                    base.SetPropertyValue(PROPERTY_MIN_POOL_SIZE, value);
                }
            }
        }

        public int CreationTimeout
        {
            get { return base.GetPropertyValueInteger(PROPERTY_CREATION_TIMEOUT); }
            set
            {
                if (value < 0 || value > 2147483647)
                {
                    throw new OverflowException("The value must be between 0 and 2147483647.");
                }
                else
                {
                    base.SetPropertyValue(PROPERTY_CREATION_TIMEOUT, value);
                }
            }
        }

        public bool ConstructionEnabled
        {
            get { return base.GetPropertyValueBoolean(PROPERTY_CONSTRUCTION_ENABLED); }
            set { base.SetPropertyValue(PROPERTY_CONSTRUCTION_ENABLED, value); }
        }

        public string ConstructionString
        {
            get { return base.GetPropertyValueString(PROPERTY_CONSTRUCTION_STRING); }
            set { base.SetPropertyValue(PROPERTY_CONSTRUCTION_STRING, value); }
        }

        public bool JITActivation
        {
            get { return base.GetPropertyValueBoolean(PROPERTY_JIT_ACTIVATION); }
            set { base.SetPropertyValue(PROPERTY_JIT_ACTIVATION, value); }
        }

        public bool EventTrackingEnabled
        {
            get { return base.GetPropertyValueBoolean(PROPERTY_EVENT_TRACKING_ENABLED); }
            set { base.SetPropertyValue(PROPERTY_EVENT_TRACKING_ENABLED, value); }
        }

        public bool MustRunInClientContext
        {
            get { return base.GetPropertyValueBoolean(PROPERTY_MUST_RUN_IN_CLIENT_CONTEXT); }
            set { base.SetPropertyValue(PROPERTY_MUST_RUN_IN_CLIENT_CONTEXT, value); }
        }

        public bool MustRunInDefaultContext
        {
            get { return base.GetPropertyValueBoolean(PROPERTY_MUST_RUN_IN_DEFAULT_CONTEXT); }
            set { base.SetPropertyValue(PROPERTY_MUST_RUN_IN_DEFAULT_CONTEXT, value); }
        }

        public bool IsPrivate
        {
            get { return base.GetPropertyValueBoolean(PROPERTY_IS_PRIVATE); }
            set { base.SetPropertyValue(PROPERTY_IS_PRIVATE, value); }
        }

    #endregion

    #region "Public methods"

        public void AssociateRole(string name)
        {

            if (_colRoles == null)
            {
                RetrieveRoles();
            }

            if (!_colRoles.AddEnabled)
            {
                throw new NotSupportedException("Associating role is not supported.");
            }

            if (this.Parent.IsSystem)
            {
                throw new NotSupportedException("Cannot associate role in a system application.");
            }

            if (!this.Parent.Changeable)
            {
                throw new NotSupportedException("The application does not support modifications.");
            }

            if (RoleAssociated(name))
            {
                throw new DuplicateNameException(string.Format("The role '{0}' is already associated with this component.", name));
            }

            COMAdminCatalogObject role = (COMAdminCatalogObject)_colRoles.Add();

            role.Value(COMRole.PROPERTY_NAME) = (object)name;

            _colRoles.SaveChanges();


            RetrieveRoles();
        }

        public void DissociateRole(string name)
        {

            if (_colRoles == null)
            {
                RetrieveRoles();
            }

            if (!_colRoles.AddEnabled)
            {
                throw new NotSupportedException("Dissociating role is not supported.");
            }

            if (this.Parent.IsSystem)
            {
                throw new NotSupportedException("Cannot dissociate role in a system application.");
            }

            if (!this.Parent.Changeable)
            {
                throw new NotSupportedException("The application does not support modifications.");
            }

            if (!RoleAssociated(name))
            {
                throw new KeyNotFoundException(string.Format("The role '{0}' is not associated with this component.", name));
            }

            for (int i = 0; i <= _colRoles.Count - 1; i++)
            {
                if (((string)((COMAdminCatalogObject)_colRoles.Item(i)).Name).ToLower() == name.ToLower())
                {
                    _colRoles.Remove(i);
                    break;
                }
            }

            _colRoles.SaveChanges();

            RetrieveRoles();
        }

        public void DissociateRoles()
        {

            for (int i = this.RolesCoches.Count - 1; i >= 0; i += -1)
            {
                DissociateRole(this.RolesCoches(i));

            }
        }

        public bool RoleAssociated(string name)
        {

            bool found = false;

            for (int i = 0; i <= this.RolesCoches.Count - 1; i++)
            {
                if (this.RolesCoches(i).ToLower() == name.ToLower())
                {
                    found = true;
                    break;
                }
            }


            return found;
        }

        public bool InterfaceExists(string name)
        {

            bool found = false;

            for (int i = 0; i <= this.Interfaces.Count - 1; i++)
            {
                if (this.Interfaces(i).Name.ToLower() == name.ToLower())
                {
                    found = true;
                    break;
                }
            }


            return found;
        }

        public COMInterface RetrieveInterface(string name)
        {

            COMInterface interfaceFound = null;

            for (int i = 0; i <= this.Interfaces.Count - 1; i++)
            {
                if (this.Interfaces(i).Name.ToLower() == name.ToLower())
                {
                    interfaceFound = this.Interfaces(i);
                    break;
                }
            }

            if (interfaceFound == null)
            {
                throw new KeyNotFoundException(string.Format("The interface '{0}' was not found.", name));
            }


            return interfaceFound;
        }

        public void Refresh()
        {

            RetrieveInterfaces();

            RetrieveRoles();
        }

        public int CompareTo(object obj)
    {


        return this.Name.CompareTo(((COMComponent)obj).Name);
    }

    #endregion

    #region "Private methods"

        private void RetrieveInterfaces()
        {

            _lstInterfaces = new ReadOnlyCollection<COMInterface>();

            _colInterfaces = base.GetCollection(KEY_COLLECTION_INTERFACE);

            for (int i = 0; i <= _colInterfaces.Count - 1; i++)
            {
                _lstInterfaces.Add(new COMInterface((COMAdminCatalogObject)_colInterfaces.Item(i), _colInterfaces, this));
            }


            _lstInterfaces.Sort();
        }

        private void RetrieveRoles()
    {

        _lstRoles = new ReadOnlyCollection<string>();

        _colRoles = base.GetCollection(KEY_COLLECTION_ROLES);

        for (int i = 0; i <= _colRoles.Count - 1; i++)
        {
            _lstRoles.Add((string)((COMAdminCatalogObject)_colRoles.Item(i)).Name);
        }


        _lstRoles.Sort();
    }

    #endregion
}

Once again, if you want to download the code, you can get it here : ComPlusInterop.zip (31.45 kb).
If you want a complete COM+ programming reference, you can check this MSDN article. This is where I got all the string needed to retrieve property values from COMAdmin.
Enjoy !

Microsoft Dynamics CRM 4.0 tabSet list

As I explained in another article, when you want to retrieve to name of the entity displayed in a CRM page it's easy to check for the etc parameter and then translate the number to a name by calling the MetaData service. But, as I also said, when you check for the page "areas.aspx", you don't have the entity number of the related entity... instead you get a tabSet parameter. The tabSet contains either the relationship name or a tabSet name...

Because the same related entity can have multiple tabSet names, I decided to list everything I found to simplify the job for you (I all got those using Fiddler and clicking on every link of related entities in CRM...).

Area name Related entity name
areaActivities ActivityPointer
areaActivityHistory ActivityPointer
areaAsyncOperations WFProcess
areaRelationships CustomerRelationship
areaRelationship CustomerRelationship
areaContacts Contact
areaSubConts Contact
areaSubAccts Account
areaAddresses CustomerAddress
areaOpps Opportunity
areaOpportunities Opportunity
areaQuotes Quote
areaOrders SalesOrder
areaInvoices Invoice
areaService Incident
areaCases Incident
areaContract Contract
areaListsInSFA List
areaCampaignsInSFA Campaign
areaProducts Product
areaSubs Product
areaComp Competitor
areaComps Competitor
areaSalesLit SalesLiterature
areaItems ProductPriceLevel
areaContractLines ContractDetail
areaRoles Role
areaTeams Team
areaServices Service
areaResourceGroup ResourceGroup
areaResourceGroups ResourceGroup
areaUsers SystemUser
areaBiz BusinessUnit
areaResource Resource
areaUnits UoM
areaPrices ProductPriceLevel
areaMembers SystemUser
areaExistingProducts QuoteDetail
SalesOrder
Invoice
areaWriteInProducts QuoteDetail
SalesOrder
Invoice

All this may save you some hours of clicking !

Posted: Apr 27 2009, 13:46 by WebMasterSam | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: .Net | CRM 4.0 | Programming
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us
LINK BUILDING IS PROHIBITED ON THIS WEBSITE