WCF With GP Web Services

by Jacob 15. March 2009 12:29

I’m at Convergence this week in New Orleans. If you’re unfamiliar with the conference (and don’t want to follow the nifty link), all you really need to know is that it’s Microsoft’s convention for their business solutions products. For me, that means Dynamics Great Plains.

I bring this up because in the last session I attended yesterday, Louis Maresca mentioned a problem I remembered having with GP Web Services. GP WS has a serious problem when you first instantiate the proxy object: it can take seconds (over 30 on our older systems—I put a timer in just to verify) to instantiate the web service proxy. The reason for this is that .Net queries the service to pull down the available methods and objects on instantiation. Since there are very many of them available in GP Web Services, the query and xml serialization adds up to quite a lot.

Now, his solution was very clever, but involved creating a new web service to slim down the contract retrieval. My solution was to saddle up and use WCF. You see, WCF doesn’t do silly things like query for contracts it already knows full well about. I cracked how to use WCF with GP Web Services about a year ago and I haven’t looked back since.

In that session last night I realized that others might want to know what it took to get it working (and thus a blog post was born…) I’m not going to go though creating the WCF bit. It’s pretty straight forward and explained all over.

Crap, I find I can’t actually proceed without at least giving an overview.

  1. Right-click your project.
  2. Select “Add Service Reference”.
  3. Fill out the dialog:

GPWSServiceReference

Okay, now that I got that out of my system there are two things that prevent WCF and GP Web Services from playing nice together.

Security

Since GP WS uses your windows identity to validate things like roles and permissions, your client needs to send the correct identity or “bad things can happen”™. In VS 2005 web services, this was a simple matter of setting .UseDefaultCredentials to true. In WCF it’s a good bit more complicated. It’s a mirror of remotely printing Reporting Services using WCF, though, so techniques used there are applicable (though slightly different).

First, you have to let the binding know the correct security mode and transport. I did this in a basicHttpBinding in the <security> section:

<security mode="TransportCredentialOnly">
  <transport clientCredentialType="Ntlm" />
</security>

I came at this setting obliquely and after much trial and error. I’m not sure why clientCredentialType=“Windows” didn’t work against GP WS when it worked with Reporting Services. Probably something quirky in our environment.

This alone is not enough, however. The binding setting is just the contract. To actually use the correct credentials, your proxy has to be told what to do. Not difficult, but easy to overlook when you’re coming from a 2005 web services background. Here’s all it takes:

DynamicsGPSoapClient service = new DynamicsGPSoapClient();
service.ClientCredentials.Windows.AllowedImpersonationLevel 
    = TokenImpersonationLevel.Impersonation;

Once that’s all taken care of, you’re set to go. Those two lines of code are processed pretty much instantaneously on even our slowest clients, so problem solved. Almost.

Errors

Error handling hung me up for a while and was the final hurdle to being able to truly implement WCF with GP WS. I was so excited when I finally figured it out that I blogged it at the time. The key point is that GP WS wants to check a user’s authorization to view errors before giving up the details of what happened so you have to hit the web service again for details. Thus, while the status message is informative, you only get a GUID for detail in the initial error. This is not a bad thing, but it leads to difficulties when putting together your excuses to the user—particularly when WCF doesn’t make it easy to get at the details of an untyped FaultException.

Simple as That

From here, everything is pretty much the same. You have your objects in the domain you specified in the “Add Service Reference” dialog given above (GPService in my screenshot). Your proxy object has the methods you can use.

Tags: , , , , ,

Programming

So You Think You're An Admin?

by Jacob 14. February 2009 22:56

Access Button I had an interesting problem crop up trying to run my own application this week. We have a routine that uses an excel spreadsheet to import orders into Dynamics GP that includes some twists that aren't handled well by Integration Manager. Since the application runs from the network (using ClickOnce) and because these orders can be substantial and represent a commitment of corporate resources, we want some control over who can run them. Specifically, we use Active Directory group membership with hard-coded/defined groups.

One of the groups I want to allow is Domain Admins. And yes, this is a kludge. All three members of our small IT shop are Domain Admins—mainly so that we can act as backup when the others are unavailable. It's a handy kludge, though, so lump it. Unfortunately, when running from my machine (running Vista), the user token being used to check Identity.IsInRole() wasn't admitting that I am, in fact, in the Domain Admins domain group

This is, by the way, the first I've run into an inversion of Works on My Machine™.
 works-on-my-machine-starburst-not

The Problem

It wasn't terribly difficult to figure out what was wrong. The key to the problem is that Vista UAC (which I actually rather like because I want to know when programs undertake certain activities) creates a “split token” when you login using an account with admin privileges. The user actually runs using the filtered token that removes the dangerous things and only elevates (with user notification and approval) when those privileges are actually needed.

So when I asked WindowsIdentity.IsInRole("COMPANY\Domain Admins") it told me that it's never heard of that role and certainly I'm not a member of it. This was disconcerting.

Now the problem goes away if you start Visual Studio with “Run as Administrator” or start an application with a shortcut with that setting. Which works fine (not great) while developing (if you remember to start VS as administrator) but eventually I got tired of it and sometimes I want to run the deployed app from my box. There's just one small hitch. Remember that I mentioned that we deploy the app to the network using ClickOnce? It turns out that there's no good way to start a ClickOnce app with elevated privileges. Googling around (and even checking Stack Overflow) I found some people who wrote what were essentially batch files or ran services that could then be used to elevate processes either to run ClickOnce apps or to allow ClickOnce apps to do stuff that requires elevation. But really, that's a lot of hassle for something I just knew had to be simpler.

The Solution

After beating my head on the problem for a bit, I eventually took a step back and asked myself that crucial dev question: “What am I actually trying to accomplish here?” I need to remind myself to do that sooner when I find myself “brought to Point Non Plus” (as Georgette Heyer's characters might say). It turns out to be a good question and one that led to the “Duh” moment I share with you now.

Since I'm not actually doing anything that requires admin privileges, going for process elevation is a complete waste of time. All I really want to know is if the current user is part of a specific Active Directory group. Didn't I see something about .Net Framework 3.5 and managed domain objects? Why yes! Yes I did!

The nifty little buggers are in System.DirectoryServices.AccountManagement and if you do anything with Active Directory domains you owe it to yourself to give this namespace a once over. Here's what I ended up with:

bool isAllowed = false;
WindowsIdentity wi = WindowsIdentity.GetCurrent();
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "COMPANY"))
{
    UserPrincipal up = UserPrincipal.FindByIdentity(pc, wi.Name);
    GroupPrincipal gp = GroupPrincipal.FindByIdentity(pc, "Domain Admins");
    if (up.IsMemberOf(gp))
        isAllowed = true;
}

This worked right out of the chute. Well, getting the right AD group membership didn't want to work when using the Principal.IsMemberOf(PrincipalContext, IdentityType, string) overload, but pulling down the actual GroupPrincipal looks cleaner anyway, I find.

Tags: , , , ,

Programming

Appreciating Alt.Net

by Jacob 22. January 2009 00:39

Appreciation I'm on record as dissenting from some of the planks of the Alt.Net bandwagon. I question design for testability and have extended that to questioning what I consider to be the over-use of Dependency Injection (though I've also talked about using it successfully in a project that I believe warranted its use). Further, in my last post, I asked if the Alt.Net folks couldn't expand their treatments of design principles to include contra-indications or fault points. I also decried those who actively stifle alternative viewpoints, though I left it vague about who I think might do so.

Given all of that, it's easy to see how some Alt.Net folks might see me as an antagonist and read my posts from an adversarial perspective.

For the Record

Realizing this, I thought I'd take a post to set the record straight. I'm glad that the Alt.Net movement exists and that there are so many quality .Net developers putting so much effort into that community. Software development is a non-trivial task with a huge range of concerns and diversity of environments. Having a group of people with an eye on broader software developments who then take the time to translate advances in other spheres into .Net is an invaluable service. Many folks in the Alt.Net crowd not only teach and explain software development advances, they work with awesome intensity to bring tools to the .Net environment that enable and promote these methods and practices.

Their passion and energy have advanced .Net development immensely and I would do nothing to take away from or diminish their achievements. We (as a .Net community) benefit from their work even if we don't implement the practices, tools or patterns they espouse. Not only do we gain from the visibility they give our platform, but we enjoy improvements that make it back into our development environment (whether through Microsoft or through tools vendors who incorporate and enable better designs).

Elitist?

So is the Alt.Net community elitist as they have been accused by some? I'd be careful about making such an accusation. Any group is going to be “elitist” if only from the simple fact that for a group designation to be useful you have to have people both inside and outside that group. Attributing a personality to Alt.Net is complicated, though, by it's amorphous definition. There's no official designation, no tribunal, no excommunication procedure—there's not even an official, endorsed doctrine. Alt.Net is a convenient designation to describe a general group of practices (and/or developers who favor or promote those practices) the details of which are in a more or less constant state of flux.

Generally speaking, those who identify themselves as a part of Alt.Net are some of the best and brightest in the .Net development community. They're smart and they have strong opinions (however loosely held) and they are willing, even eager, to express those opinions when given half a chance. Smart people expressing strong opinion can come across to others as elitist but I don't think that is an accurate description of Alt.Net as a rule. At worst, you can describe them as having high standards and the guts to promote the advantages of adhering to those high standards.

That's not to say that there aren't those in their ranks who sometimes behave arrogantly. As I described in my last post, I was stung by the public remarks of one prominent Alt.Netter and his casual disregard for my post and for me personally. I wouldn't, however, paint that incident as either representative of Alt.Net as a group, or even as representative of that specific person.

Painting the Alt.Net community as “elitist” can be simply an excuse to disregard them and their practices and I think doing so is a mistake. Even if they were a bunch of elitist jerkwads (which, again, I do not consider them to be), the fact remains that their ideas and principles are valuable and ignoring them will only hurt you. I may disagree with the broad applicability of Dependency Injection, for example, but I'm glad I learned the concept from them so that I was able to use it when I ran into a situation that was pretty much tailor-made for that pattern.

Transparency

One of the reasons Alt.Net suffers the slings and arrows of their detractors is that they take pains to be transparent. Their email list is open (and public), many of them are prolific bloggers, and they aren't afraid to speak up when they disagree with each other. This transparency can lead to unfavorable comparisons to organizations that are less open (like, say, the Patterns and Practices group at Microsoft). Such comparisons are misleading at best.

Laying your disputes out for public observation can make you look weaker than you really are because people will use those disputes as an excuse to ignore your strengths.  It's easy to miss the reverse side of that coin—being open allows your ideas to be broadly tested and honed. It takes a certain degree if intellectual fortitude to operate transparently, but being able to do so leads inevitably to stronger solutions, principles, and practices.

Those who are willing to put their ideas out there with warts and all deserve respect. I, for one, am happy to give them the respect they've earned (even as I remain willing to question individual applicability in my own development).

Tags: , , ,

Programming

Professional Development

by Jacob 14. January 2009 15:22

Baby Developer Many of the interesting .Net bloggers are part of the Alt.Net crowd; evangelizing Dependency Injection, Design for Testability, Test Driven Development, SOLID design and other development practices that they find useful in their work. It doesn't take long reading these blogs to pick up on what looks like an unforgiving attitude towards those who don't use the latest acronyms in their software development.

This acrimony is unfortunate because most often what is at the heart of those who question the standard Alt.Net toolset isn't so much principle as it is context.

A Fundamental Assumption

Unfortunately, discussing software development at all imposes an initial assumption that too often goes unexamined—the assumption that the software development you are doing is substantially similar. I'm afraid that this assumption is violated more often than we realize.

Most prominent development bloggers are consultants, conference speakers, tool vendors, or framework providers of one sort or another. As such, they are used to considering the problems of very large applications with many cross-cutting concerns. Is it any wonder, then, that they are strident about the importance of segregation and testing? For the majority of their hands-on development, everything that increases separation and independence is a benefit because isolating fail points and mitigating the cost of touching individual elements carries a heavy multiplying effect on overall complexity. No wonder they want to use a DI framework on every project and insist that other developers practice TDD. It's all up-side in such projects because the costs disappear in the noise and the benefits stand out.

Not all of us work in those kinds of environments and/or applications, however. Many of us work on projects that are wildly dissimilar. Our applications are narrowly focused, single use, and with limited distribution. For us, implementing solution-wide DI eats up half the project configuration overhead and delivers functionally zero chance of eventual benefit.

I'm unsure how many find themselves in similar (smaller) development shops. I suspect quite a few. We might even be a majority of actual, working developers. We're pretty much absent from the development blogger population, however.

A Problem

What that means for us small-shop developers is that we end up having to do a lot of on-the-fly translation. Up-scale bloggers have shown themselves averse to “thinking down” so we end up having to analyze the methods and techniques they discuss to see where the fail points are for our projects. If your QA team is the folks in the warehouse and your architecture a straight-on table insert, is TDD really going to pay off? What about bug tracking? Or continuous integration?

These translations are interesting and part of why I like smaller development. Our problem space is largely undiscovered country. We can't really trust anything labeled “best practice” and we have to do our own experiments to find what works and what doesn't and at what point it starts to make sense to engage different methodologies.

It'd be nice, though, if some of the gee-whiz bloggers would discuss the fail points of their methods and tools. Or point out the trade offs that various techniques are likely to entail. No technique or method is so useful that it is universally applicable, so where are the borders?

Worse, though, are those who actively stifle discussion of such fail points. Mention that you'd rather not use Dependency Injection, for example, and you can find your professionalism and/or intelligence questioned. Indeed, for many the very fact that you don't <insert favorite practice here> indicates that you must never have tried it. Or if you have you must have been doing it wrong.

This friction fosters resentment and shuts down discussion. Perhaps one reason we don't see more developers willing to discuss alternatives to the popular band wagons of today is a reluctance to enter what amounts to a hostile arena. As the troubles on Wall Street filter down to Main Street (where us small-shop developers live) the last thing we need is other developers calling us unprofessional in public. Particularly when those other developers are well-known and respected in their community.

I know this from personal experience. I'm pretty secure in my current position. My company is healthy and has a marked competitive advantage that I am key to delivering. My boss respects me as do the owners of the company. Even so, my gut clenched tight and my heart sank to my knees when I came across a twitter message from a luminary in our field (someone any informed .Net developer would recognize) dismissing me as unprofessional and my points as unworthy of consideration.

Seeing something like that will make you wonder if expressing your doubts is worth the risk, even when it isn't directed at you.

Tags: , , , ,

Programming

Changing Table Names in an OR/M

by Jacob 27. August 2008 11:33

Empty Sign I spent some quality time googling this and even went and asked the nascent Stack Overflow community and didn't come up with a satisfactory answer. Being the intrepid sort, I opened up a test project and started poking around, compiling information from a number of sources and playing until I got something that worked. For your amusement and/or edification, I'll document what I found.

What I Want to Do

The basic scenario is that many typical “commodity” web applications use databases to store their information. Since most web hosting services come with a single database but charge extra for additional databases, it is common for web-type products to add identifier text to their table and stored procedure names*. The .Net blog software I sometimes contribute to, Subtext, is an example. Take the table I added to hold tags associated to posts a while back, “subtext_Tag”. Using the “subtext_” prefix means that we won't run into naming collisions on our tables if someone has a wiki or forum application that also contains a table for tag entities named “Tag”.

 

* And yes, as one user on Stack Overflow suggested, you could use schema as a differentiator so we could as easily have used a “subtext” schema and our tables would be “subtext.Tag” instead of “dbo.Tag”. That solution is much trickier to setup than a simple table naming convention, though, so I think I prefer the table prefix for now.

 

The .Net Way

While I was initial open to any .Net OR/M the fact of the matter is that the only one I know anything about is SubSonic. Now I like SubSonic a lot, but their tools are geared towards code generation and I couldn't find a handle into runtime manipulation of table names (such might exist, but I was unable to find it).

Since I'm even less familiar with the other third party .Net OR/M data tools (like LLBLGen or NHibernate) and nobody on Stack Overflow (who tend to be knowledgeable about these things) spoke up, I decided to check out what it would take to monkey with the table names at runtime using stuff I have actually used. Namely the Entity Framework and LINQ to SQL. It turns out to be possible in either, though I have to admit to being surprised that it is easier in LINQ to SQL than in EF.

My Test Database

To keep things simple, I created a test database. Since I am a highly creative professional, I named it “Test” and created a table there named “TestTable”.

Test Schema 

LINQ to SQL

Instantiating a new DataContext object in LINQ to SQL includes a constructor that allows you to feed in a MappingSource derivative. By default, L2S uses an attribute mapping object that pulls the metadata from attributes on your classes—in this case the “Name” property of a TableAttribute.

[Table(Name="dbo.TestTable")]
public partial class TestTable : INotifyPropertyChanging, INotifyPropertyChanged
 

Since attributes are immutable at runtime, using the default isn't an option here. Fortunately there's an XmlMappingSource object that can use an XML file (or fragment) to do what I need. Unfortunately, generating an initial mapping file is a touch cumbersome and requires use of the SQLMetal.exe tool provided with Visual Studio.

Here's how (after adding a TestLINQ.dbml file and dragging the table onto it—pre-name-change of course):

  1. I opened the VS Command Prompt (it's in a Visual Studio Tools folder in the start menu).
  2. Changed the directory to my project.
  3. Entered the command “sqlmetal /map:TestLINQ.map /code TestLINQ.dbml”. This generates a TestLINQ.map file.
  4. Right-clicked on the generated file in my project and selected “Include in Project”.
  5. Set the file's “Copy to Output Directory” property to “Copy Always”.

The mapping file is pretty simple. The relevant bit is the Name attribute of the Table element:

<Table Name="dbo.test_TestTable" Member="TestTables">
  <Type Name="LINQ.TestTable">
    <Column Name="TestId" Member="TestId" Storage="_TestId" DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" IsDbGenerated="true" AutoSync="OnInsert" />
    <Column Name="TestOne" Member="TestOne" Storage="_TestOne" DbType="VarChar(50)" />
    <Column Name="TestTwo" Member="TestTwo" Storage="_TestTwo" DbType="VarChar(50)" />
  </Type>
</Table>
 

Make sure the name is what you want it to be and you're golden. Here's the code I used to test it out after the name change.

XmlMappingSource source = XmlMappingSource.FromUrl("TestLINQ.map");
using (LINQ.TestLINQDataContext context = new LINQ.TestLINQDataContext(Properties.Settings.Default.TestConnectionString, source))
{
    LINQ.TestTable table = new LINQ.TestTable()
    {
        TestOne = "firstLINQ",
        TestTwo = "secondLINQ"
    };
    context.TestTables.InsertOnSubmit(table);
    context.SubmitChanges();
 
    table.TestOne = "thirdLINQ";
    context.SubmitChanges();
 
    context.TestTables.DeleteOnSubmit(table);
    context.SubmitChanges();
}
 

XmlMappingSource even has a .FromXml() method that will create your map from an Xml fragment string.

Entity Framework

As I mentioned before this one is harder. This is a surprise because EF is ostensibly created to make it easier to keep your object definitions separate from your storage definitions. The reason it isn't easier is understandable once you realize that EF is made to be highly configurable and thus its definition files are much more complex than the L2S mapping.

The first problem with EF, though, is that the documentation is schizophrenic. Also confusing. That's because MS rolled the original three configuration files into the .edmx definition file so references on the web imply that those files are easily seen and edited. Even more confusing is that EF actually still uses the .csdl, .ssdl, and .msl files at runtime—it just generates those files from the .edmx and either packs them in the assembly as a resource (by default) or as files in your output directory.

Well, to monkey with the tables at runtime, you have to have access to the configuration files. To do so you need to change the default in the “Metadata Artifact Processing” property of your ConceptualEntityModel and rebuild the project. That'll put perfectly good .csdl, .ssdl, and .msl files in your output bin directory (You don't have to leave it at "Copy to Output Directory" once you have saved these files off for your own use and abuse.)

EF did another funky thing by deviating from the norm in what it pulls from the connection string that you feed it. If you look at your EF connection string in app.config (or web.config) you'll see something like this:

<add name="TestEntities" 
connectionString="metadata=res://*/TestEF.csdl|res://*/TestEF.ssdl|res://*/TestEF.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=localhost;Initial Catalog=Test;Integrated Security=True;MultipleActiveResultSets=True&quot;"
providerName="System.Data.EntityClient" />
 

Notice that there's a “provider connection string” embedded in the connectionString attribute—that's the “normal” connection string that tells EF what database to use for storage. Also notice that the metadata property tells EF where to go for those configuration files (in this case, it's telling EF to look in the assembly for resources TestEF.csdl, TestEF.ssdl and Test.msl).

Armed with this information, I was able to add a set of generated config files to the project stolen from those generated in the output directory. Once there, you have to edit the storage file and the mapping file to use the altered names. The table name used by EF is taken from the Name attribute of the EntitySet element in the .ssdl file. This is unfortunate because the Name attribute is a reference used by things like associations. Which means that you have to make sure you alter all the references to that EntitySet as well (fortunately, these are generally referenced using an EntitySet attribute on the relevant association and thus are relatively easy to find).

<EntitySet Name="test_TestTable" EntityType="TestModel.Store.TestTable" store:Type="Tables" Schema="dbo" />
 

It's not necessary to alter the EntityType, though I found that if you alter it consistently across the file it will work if you do.

The mapping configuration in the .msl file just has to be updated so that the objects use the correct EntitySet for storage.

<EntitySetMapping Name="TestTable">
  <EntityTypeMapping TypeName="IsTypeOf(TestEF.TestTable)">
    <MappingFragment StoreEntitySet="test_TestTable">
      <ScalarProperty Name="TestId" ColumnName="TestId" />
      <ScalarProperty Name="TestOne" ColumnName="TestOne" />
      <ScalarProperty Name="TestTwo" ColumnName="TestTwo" />
    </MappingFragment>
  </EntityTypeMapping>
</EntitySetMapping>
 

Once those changes are made your code will work with the altered table name, though you need to alter the connection string to look for the correct configuration files. Here's the final code I used to test it out.

string connection = "metadata=TestEF.csdl|TestEF.ssdl|TestEF.msl;provider=System.Data.SqlClient;provider connection string=\"Data Source=localhost;Initial Catalog=Test;Integrated Security=True;MultipleActiveResultSets=True\"";
using (TestEntities entities = new TestEntities(connection))
{
    TestTable table = new TestTable()
    {
        TestOne = "firstEF",
        TestTwo = "secondEF"
    };
    entities.AddToTestTable(table);
    entities.SaveChanges();
 
    table.TestOne = "thirdEF";
    entities.SaveChanges();
 
    entities.DeleteObject(table);
    entities.SaveChanges();
}

So Which is Better?

Well, that depends on what you want to accomplish but then, doesn't it always? For me, the LINQ to SQL solution is much cleaner because I'm simply not going to use all the other goo that the Enterprise Framework includes. Plus, the LINQ to SQL solution can use an XML fragment so I can bury that mapping piece wherever I want to, including in inline code. EF requires a file reference so those files have to be either in the assembly resources or on the file system. EF also allows you to leverage Asp.Net Data Services but that's a topic for another post entirely...

Tags: , , , , , , ,

Programming

Testability in .Net

by Jacob 15. August 2008 08:02

Tester Your environment can have a profound effect on how you develop software. The details of what I discuss here have zero practical meaning outside of the .Net world (though you can probably find parallels in other environments). That's because .Net developers have access to tools that invalidate rules of software design that are fundamentally important elsewhere (before you question whether an environment can effect what is good design, consider the difference between good design in C and, say, Prolog). For .Net, the free availability of a tool like Typemock makes a major design consideration simply disappear—namely, testability. Typemock literally robs the term “testability” of meaning in .Net design considerations. That's a freedom that should leave other developers gasping in envy.

Typemock's Magic

I don't want to be a running commercial for Typemock here (they're certainly not paying me to say any of this), but it is a truly revolutionary tool and its effect on development in .Net needs to be examined and understood. The thing is that using Typemock means that you can unit test literally any public method of any public class, regardless of any and all internal dependencies that class might have. And you can do so without changing the design and/or architecture of your software at all.

In other words, using Typemock means that everything is testable. Unit testable. Seriously. Everything.

Profound Effect

Stepping into a world where literally everything is testable is like stepping into a world where you wake up at a designated spawn point instead of dying—fundamental considerations about what is risky and what isn't need to be remapped. Which makes listening to .Net developers discuss testability considerations of various designs a little like listening to World of Warcraft players who are afraid to get too attached to characters that might die—it seems like a lot of effort for something that has little meaning.

Which is why I had such a hard time reading Jeffrey Palermo's latest blog post entitled “Inversion of Control is NOT about testability”. Since I know Jeffrey Palermo is a .Net developer, my initial response is a big fat “Duh. He must be using Typemock.” Sadly, this is not the case.

Freeeeeeedom!

That's too bad because there are some very interesting things in that post that get obscured by continually dragging in testability. For one, he gives a good explanation of Inversion of Control accompanied by a discussion of why you might want to use it outside of unit testing. His statements about coupling in particular piqued my interest. He said:

NOTE: There is no such thing as LOOSE COUPLING.  There is coupled, and not coupled.  Either a type is coupled to a type or it is not.  More accurately.  Loose coupling exists much like the concept of "cold".  When we say "close the door, you'll let the cold out" on a hot day.  Cold doesn't exist.  Either heat is there or it isn't.  We use cold to communicate, but it serves as a shortcut for the lack of heat.

Now, he got hold of a bad analogy (because there are degrees of heat—it's not a binary value—so there is nothing wrong with describing something as “less hot” just as we say "less coupled") and his point is technically wrong (because whether you call it loose, deferred, proxied, or something else, when you are coupled to an interface that a class implements, you have a relationship to that implementing class that is similar enough to coupling that an adjectival modifier is an acceptable descriptor) but the core of his point is still a good one. Tying your class to an interface is a profound change and it is probably a good idea to examine what “loose coupling” means (i.e. how “loose” modifies a coupled relationship).

He later said something I found profound:

In order to do anything useful in software, you must couple. You must couple to something. (emphasis his)

and he later concluded with

You must decide where coupling is appropriate and where it is not.

Importing Designs

Here's why it's a tragedy that Jeffrey didn't make use of his Typemock-granted freedom from testability concerns: that's all he said about coupling. He wasted so much unnecessary time with things that have no value or meaning in a .Net environment that he didn't better explore what coupling means and when to mask coupled relationships.

And here's my wider point: concerns about testability are imported from other environments. .Net folks discuss testability as if it has value in and of itself (because in other environments it does). We forget that testability is no more of a first-order good than quality is. “Testable design” only has value in the things it allows us to do—namely, unit test our classes. If we can unit test our classes as easily no matter what design patterns we choose, then that frees us up to explore other aspects of design choices. It isn't that <le design du jour> ceases to have value, it's just that testability is no longer a factor in evaluating its utility.

Those that realize this will have a competitive advantage over those who do not. If I can test no matter my project structure, then I can choose a design that more exactly fits other aspects of my development needs. Which means I can allocate resources more efficiently than someone who has design concerns that don't fit the actual environment. I can choose <Der Entwurf des Tages> when and where it is actually, immediately useful instead of doing so in order to achieve testability. And efficiency kicks butt in the marketplace.

So, uh, forget all I just said. Spend lots of time making sure your .Net projects are testable. Also: Typemock sucks. Don't bother going there...

Tags: , , , , ,

Programming

Custom Dynamics Warehousing

by Jacob 4. January 2008 03:25

Warehouse Prior developers and others who should have known better at my company decided many years ago that our warehouse people simply could not do their jobs unless we unleashed the ability for them to use multiple "bin" locations for each item. Now, strictly speaking, this was not really the case, because our needs simply aren’t that complex. We manufacture reading glasses so we don’t need inventory aging and all the warehouse people really needed were different sites to separate receiving from QA from shipping. In other words, we have product staging, but each stage is physically as well as conceptually separate and each item in each stage exists really only in a single location.

As in so many real-life situations, however, there is enough cruft built up around the current process that it is simply not worth expending the political capital to change. Which means that I’m stuck trying to automate order fulfillment for multiple bins with multiple locations.

The Tools

Now, Dynamics has a number of interesting tools and my company long ago purchased all the neat bits that I need to use them all. The typical default tool that people use to customize Dynamics is a hoary old beast called "Dexterity". I’m sure that the name once fit, but in an honest world the name would have long ago been changed to "Decrepit". I’ll use Dexterity if I absolutely have to, but I’ll avoid it more assiduously than, say, rabid ninja porcupines.

Fortunately, Microsoft, feeling their oats with cool technologies like the .Net framework and web services and all, has released developer tools that includes a .Net toolset to create addins and a set of web services that can be used to perform most business tasks. I also have the Database schema if I have to resort to direct table access, but I tend to avoid that if I can (though not at the rabid ninja porcupine level).

There are some important things to know about these tools.

.Net Integration

The .Net integration can hook into Dynamics forms and events and play with field values. You can also create your own forms and hook them into a special "Extras" menu when a given Dynamics form is active (or have them pop up during an existing event handler I suppose).

They didn’t skimp on the event handles, either. Each field has before and after change and click events, buttons have before and after click events, and forms and windows have activate, open, close, and print (all with before and after handles).

Web Services

The web services are more complicated to set up and are best off installed on your database server. They use some of the older E-Connect com objects in the background which makes it a pain to set up, but they’re pretty useful once you do.

The web services expose a large number of create, update, get, and delete methods for all the stuff you’d expect—customers, invoices, sales orders, purchase orders, that kind of thing. They can be a bit temperamental when it comes to setting up the policies for the operations, but once you’ve got them working, they work well.

The Problem

When we receive orders from Nordstrom, we have two factors that complicate our work flow. The main difficulty is that printing our shipping and invoice labels is a fiddly piece of work that can result in fines from Nordstrom if we get it wrong. Some long forgotten "genius" managed to get them formatted correctly using our EDI software. This is the software that is still using FoxPro as their interface and data storage. It’s a hunk of junk, but it works. More or less.

Unfortunately, for those labels to print correctly, the EDI software has to do the Dynamics import itself (instead of using my cool new EDI processing service). If the EDI software doesn’t do the import, it doesn’t know all the right invoice ids and associated stuff to print on those labels.

Also unfortunately, the EDI program knows nothing about our multiple bin fulfillment requirements. Adding to the pain is the fact that Dynamics cannot handle automated fulfillment for multiple bins on its own—particularly when certain sites are to be allowed, others avoided, and one or two bins excluded manually (yeah, we did all that to ourselves).

Since we get orders for hundreds of items at a time, this largely manual process for Nordstrom is taking a single very kind and patient person (who may or may not ever read this) about four hours. The bulk of this time is manually assigning bins to all the items on each order in the batch.

My Solution

We’ve been working on making all of our customizations accessible within Dynamics, so it’s best if an automation solution kicks off from there. The .Net tools make this part relatively easy.

public class OrderFulfillmentAddIn : IDexterityAddIn
{
    // IDexterityAddIn interface
 
    public void Initialize()
    {
        Dynamics.Forms.SopBatchEntry.AddMenuHandler(AddOrderFulfillmentMenu, "Allocate Bins");
    }
 
 
    static FulfillmentForm form = new FulfillmentForm();
    static void AddOrderFulfillmentMenu(object sender, EventArgs e)
    {
        if (form == null || form.Created == false)
        {
            form = new FulfillmentForm();
        }
 
        form.BatchId = Dynamics.Forms.SopBatchEntry.SopBatchEntry.BatchNumber.Value;
        form.Show();
        form.Activate();
    }
}

This inserts an "Allocate Bins" menu item on the extras menu when the Batch Entry form is open. The menu item opens my own form (which isn’t any great shakes). However, because the .Net integration tools are only able to handle user-initiated events and already open form fields actual bin allocation has to happen some other way.

Yeah, I chose to use the web services.

Complicating this further, the web services don’t expose anything that will give me all the bins that contain a specific item so I’ll need to pull that information from the tables directly. Fortunately, Dynamics has a handy Resource Descriptions tool that helps here.

Dynamics Resources 

It can take getting used to, but it tells me that I need table IV00112.

ItemSiteBinMaster Table

With that information, this becomes a simple Linq query.

You Want Tests With That?

Now, this is where things get tricky because I like to test my code once or twice before deployment. Oh yeah, and sometimes I’ve even been known to create unit tests and such. Which means that I have to be able to run this in both our test company as well as the live one.

Since Dynamics keeps each company in a separate database, this means that I need to know both the Company Id to feed the web service and the database name for the Linq query. This actually held me up for quite a while. My first impulse (that actually worked out relatively well) was to put both into the app config.

Linq already has it’s connection string there so I’d just need to add a CompanyId setting.

<connectionStrings>
  <add name="Integration.GPWebServices.Properties.Settings.myConnectionString"
      connectionString="Data Source=MyServer;Initial Catalog=MyDB;Integrated Security=True"
      providerName="System.Data.SqlClient" />
</connectionStrings>
<applicationSettings>
  <FulfillOrders.Properties.Settings>
    <setting name="CompanyId" serializeAs="String">
      <value>2</value>
    </setting>
  </FulfillOrders.Properties.Settings>

This worked well on the surface, but it was kind of clunky when it came to developer testing where I went into the test company within Dynamics and created batches and orders with the Visual Studio debugger attached.

That’s when the apple fell out of the sky and I realized that, duh, I have the Dynamics environment right here already. It took me a while to figure out that the database name is held in the "IntercompanyId" global property, but once I’d tracked that down, we were golden.

Orders.FulfillByBatch(BatchId
    , (int)Dynamics.Globals.CompanyId.Value
    , Dynamics.Globals.IntercompanyId.Value);

The unit test can still pull it from the config file, but my form can simply use the company currently open.

Doing the Work

I’ll give you my worker class just for kicks here. Note that allocating bins for hundreds of items takes long enough that we definitely need UI feedback (we love thee oh progress bar). That means that much of the class real estate is taken up with events that help keep my users from freaking out.

using System;
using System.Collections.Generic;
using System.Text;
using Integration.GPWebServices;
 
namespace FulfillOrders
{
    public static class Orders
    {
        public static event EventHandler OrderProcessed;
        public static event EventHandler<BeginFulfillingEventArgs> BeginFulfillment;
        public static void FulfillByBatch(string OriginalBatchId, string NewBatchId, DateTime CancelDate, int CompanyId, string CompanyDb)
        {
            Utility.DataBase = CompanyDb;
            Utility.CompanyId = CompanyId;
            SalesDocumentSummary.BeginLoadingSummary += new EventHandler<BeginSummaryLoadEventArgs>(SalesDocumentSummary_BeginLoadingSummary);
            SalesDocumentSummary.DocumentLoaded += new EventHandler(SalesDocumentSummary_DocumentLoaded);
            List<SalesDocument> orders = SalesDocumentSummary.GetSalesDocumentsByBatch(OriginalBatchId);
 
            if (orders.Count > 0)
            {
                OnBeginFulfillment(orders.Count);
                foreach (SalesDocument order in orders)
                {
                    order.BatchId = NewBatchId;
                    order.Date = order.UserDate1 = order.UserDate2 = order.ReqShipDate = CancelDate.Date;
                    order.AllocateBins();
                    order.CommitDocument();
                    OnOrderProcessed();
                }
            }
        }
 
        static void SalesDocumentSummary_DocumentLoaded(object sender, EventArgs e)
        {
            OnOrderProcessed();
        }
 
        static void SalesDocumentSummary_BeginLoadingSummary(object sender, BeginSummaryLoadEventArgs e)
        {
            OnBeginFulfillment(e.TotalOrders);
        }
 
        private static void OnBeginFulfillment(int total)
        {
            EventHandler<BeginFulfillingEventArgs> begin = BeginFulfillment;
            if (begin != null)
            {
                begin(null, new BeginFulfillingEventArgs(total));
            }
        }
 
        private static void OnOrderProcessed()
        {
            EventHandler processed = OrderProcessed;
            if (processed != null)
            {
                processed(null, new EventArgs());
            }
        }
    }
    public class BeginFulfillingEventArgs : EventArgs
    {
        internal BeginFulfillingEventArgs(int total)
        {
            Total = total;
        }
        public int Total { get; set; }
    }
}

Wrapping it Up

Integration.GPWebServices is my own library and it uses shell classes to simplify working with the GP web service objects (including the static Utility class used to store the Company Id and Database).

Wrapper Classes

Enlarge to see it in full, including the nifty methods used to put the web service objects together.

Isolating the web services also means that the WCF objects are fully encapsulated and I don’t have to worry about referencing those libraries or be concerned when they cross app boundaries. It does mean that I have to be careful with the app.config files that contain my WCF endpoint connectivity, however.

Integration.GPWebServices probably deserves it’s own post. It’s certainly large enough and it is getting relatively well polished at this point. Also, it has become great personal example of the benefits of ruthless refactoring in a case where the initial design was solid to begin with.

Tags: , , , , ,

Programming

Dependency Injection

by Jacob 7. August 2007 15:08

Dependency Injection is a design pattern used to abstract a provider from the class using it. Specifically, the calling class assumes responsibility for managing the provider instead of the class being called. Data access is a classic example of a provider that can be injected into classes that use it. If you decide to implement the DI pattern in a data access project, the most common method of doing so is to add an interface parameter on the constructor of each class that needs data access.

A C# Example

A class that accesses data might look like this (if it were programmed by chimpanzees. Or for an illustrative example.)

Original Orders

I’m using the provider factory to pull the connection details from the application configuration file but otherwise this is pretty standard. Getting the data would require creating the object and calling GetData.

CallOrders
Dependency Injection

Dependency Injection would have me change the base class so that I pass an interface into the constructor. In this case, I can probably choose whether I inject the DbProviderFactory or DbConnection, but since DbConnection already has a handy interface, that’s definitely the best way to go:

DIOrders

The benefit to this pattern is that the class is now disconnected from the data provider. The disadvantage is that now my calling code has to handle the provider.

DICaller

Dependency Injection Dissected

Functionally speaking there’s not really that big a difference between the original version and the one with the dependency injected. In all, the actual complexity of the code is a wash in my opinion.

Either way, I’m better off with an abstracted data provider (as handled in the factory classes). Either way, I need to make sure the project is consistent in how it creates the access providers (I’d probably create an internal utility class with a static method to pull down the connection, so don’t let the extra lines above distract you).

That said, dependency injection doesn’t scale well and creates opportunity for future versioning pain should you find you later need to add providers. What if, for example, I need two data connections instead of one for my class because some of my data is being pulled from a second data source. I would then need two parameters on my constructor. I could move the injection point to the methods instead of the constructor so that only the affected methods have the signature change (a not-uncommon DI method if only a small number of methods have the dependency), but generally that just pushes my problem down to where it affects more code.

And yeah, providers shouldn’t change often and there shouldn’t be more than one or two so this isn’t a huge concern. I just hate breaking encapsulation and even a small hit to your orthogonality can be significant if you find you ever have to change it.

Dependency Injection’s Natural Domain

The real reason that DI has become so popular lately, however, has nothing to do with orthogonality, encapsulation, or other "purely" architectural concerns. The real reason that so many developers are using DI is to facilitate Unit Testing using mock objects. Talk around it all you want to, but this is the factor that actually convinces bright developers to prefer DI over simpler implementations.

I do wish that people would admit that DI doesn’t have compelling applicability outside of Unit Testing, however. I’m reading articles and discussions lately that seem to take the superiority of DI for granted. And I’ve read mock object examples that seem a little bit condescending about dependency injection--as if your projects should already incorporate this technique. I wonder if this is a defensive reaction because the authors of the examples don’t want to have to justify making you fundamentally alter your coding habits and re-write all of your existing code just so that you can use their pet objects.

Superior .Net Mocking

All of this becomes particularly exasperating in the dead silence regarding TypeMock. I blogged about this product as soon as I found it because their claims are simply stunning. TypeMock claims to allow you to mock objects used by your classes without having to expose those internal objects at all.

I have completed a project using TypeMock for my Unit Testing and I can verify that they are correct.

No interface creation or injection required. No dependency injection at all. No change to how I want to create my objects. No orthogonality issues hidden like a time-bomb in my code, however tiny. TypeMock uses reflection to intercept pesky calls and has robust assert, parameter, return object and verify options. The ability to select which calls to mock and which to let the original objects handle is an outstanding unlooked-for bonus.

Best of all, TypeMock is free to use. Yeah, it’s easier to use their professional and/or enterprise products because there are improved ease-of-programming objects in those editions, but their community edition has all of the actual functionality and none of the cost.

What Gives?

So tell me; what gives? Why the resounding silence around this tool? If it works, why isn’t every .Net developer on the planet talking about it. If it doesn’t why aren’t they reviling TypeMock for taunting us so cruelly? I’m serious. Why isn’t this sucker taking the Unit Testing space by storm? And why am I still hearing about the virtues of a pattern whose sole perceptible benefit is allowing mock objects in Unit Tests?

Tags: , , , , , ,

Programming | Software

Hacking SubText

by Jacob 13. December 2006 18:34

Okay, I've had SubText up and running for a week and some now, so naturally it is time to tinker. In poking around, I'm not as happy with SubText's integration model as I was with DasBlog's. DasBlog exposed a number of "macros" that you could use to insert certain internal values into your own stuff. I kind of liked their model because once you registered your own code, you could reference your macros from DasBlog stuff as well (bear in mind that I didn't actually implement DasBlog, so my impression could be off).

That said, as long as you don't need to access things like entry links or other internal blog workings, it's pretty easy to modify a "Skin" in SubText to add new stuff. SubText reads a main ASP.Net Web User Control called PageTemplate.ascx that holds essentially the format for the other Web User Controls that a SubText site uses. Which subcontrols are used are pretty much determined by this PageTemplate control and the controls it references. This structure made it pretty easy for me to add a new embed control I wanted to play with.

The Technorati Embed

There are a number of sites that offer badges, embeds, and other tools intended for their users to simultaneously spruce-up their own sites and provide free advertising for the service involved. The Technorati search feature on the right is an example and was my first foray into modifying my blog template. With Technorati, the tag I need to use to expose a Technorati search link is this:
<script src="http://embed.technorati.com/embed/xw5vkfrkzb.js" type="text/javascript"></script>

To pop it on there, I just added that code right in the PageTemplate.ascx file where I thought it'd do some good (using a text editor). Straightforward, but inelegant.

The Great Games Experiment Embed

 For my next trick, I wanted to see how SubText would handle it if I mimicked their own structure to create a new control. To do this, I created a couple of things that are way more complicated than they needed to be. I mean, technically, all I needed to do to pop the user embed onto my site is copy the badge tag from their site in the same place I put the Technorati stuff. The tag isn't all that complicated:
<iframe src="http://www.greatgamesexperiment.com/greatgamesbadge/user/Jacob" height="140" width="204" scrolling="no" frameBorder="0" />

Doing so would produce this handy "badge":

But I'm a geek and I wanted to test some stuff out, so instead of simply pasting a bunch of html, I created a .Net project and two custom web user controls. One of the controls creates a user badge. The other control creates a game badge. The result of this project is that you can drag one of these controls onto an ASP.Net page and set the "UserName" property (or "Game" property for a game badge) and it'll take care of the rest. The active html would look like this:
<cc1:GreatGamesUserEmbed ID="GreatGamesUserEmbed1" runat="server" UserName="Jacob" />

Somehow, I managed to get that to work. As long as you've registered my assembly for the right tag prefix, you're golden.

But that wasn't quite enough for me, oh, no. Simply adding that control to PageTemplate would be kind of hokey and out of place, so I went one further. Following the pattern of the other controls, I created a GreatGames.ascx file under the Controls directory and referenced that instead. It's a simple file, but then, most of those Control files are. It creates a section that fits in much better on the right side bar and groups the Great Games badges together more naturally.

And wonder of wonders, it worked first time. Love when that happens.

Wrap-up

SubText doesn't have any documentation that I could find detailing these steps, so making these modifications required mucking about in the code to follow their flow during page delivery. If I get the gumption later, I'll re-write this as a more generic how-to in creating very basic SubText add-ins because the community needs something like this. Also, I saw a couple of interesting objects that look like you can extend them for more complicated things (like controls that access the SubText data, I'll bet). I'm sure that Phil Haack and others could point those out. In fact, they're nice enough folk on their dev email list I'd bet they'd be happy to answer questions if I took the time to ask.

Also, if you want those Great Games controls, download the source code. It's nothing fancy, but does the job. Or, if you just want the binary, download that instead. The source code project includes my GreatGames.ascx file as well so you can see an example of implementing them. Let me know if you do anything interesting with them.

Tags: , , , , , , , , , , , ,

Programming | Software

Creating a Domain Publisher Cert for a Small Internal Software Shop

by Jacob 5. December 2006 01:33

The trend towards increasing security introduces a number of intricacies for medium-sized business software shops using Active Directory Domains. An internal domain with more than a dozen workstations can introduce issues that are old hat for larger shops, but way beyond anything a small business will have to deal with. I ran into one such issue recently when I decided it'd be a cool thing for one of my apps to actually run from the network.

The Problem

The first sign I had a problem was when a module that worked fine locally threw a "System.Security.SecurityException" when run from a network share. It told me that I had a problem at "System.Security.CodeAccessPermission.Demand()" when requesting "System.Security.Permissions.EnvironmentPermission". Since it worked fine while local, I figured I had a code trust problem and that I could probably get around it in the .Net Framework Configuration settings and push a domain policy that would update everyone.

I knew this because I had run into something similar once before (deploying a VSTO solution on the network).

Here's where it pays to be a real (i.e. lazy) developer: since I've run into this before, wouldn't it be nice to come up with a solution that will make it easier when I run into this in future? There are four ways to do this, I figure (well, that I could think of, there are probably more).

  1. Create some kind of scripting solution for deploying future projects that automatically creates policies (and propagates them) for each new assembly.
  2. Create a standard directory on the network that can be marked as "trusted" and deploy any trusted code into that directory.
  3. Use a "developer" certificate as your trusted publisher.
  4. Figure out how to get a publisher cert to use to sign your code and then propagate a rule certifying that publisher as trusted.

Some developers would go with number 1. Which makes me shudder. Anyone using the first option isn't someone I want to code with or after (barring some quirky deployment requirement that makes it more attractive, of course). Number 2 would probably be the most common solution because it's pretty simple and most medium-sized businesses are used to security compromises that use "special knowledge" and a lack of being an attractive target for security trade-offs. Number 3 would be a little more "upper-crust", mainly from people who had tried 4 and run into difficulties. And frankly, for most cases Number 3 is likely adequate. The problem is that using number 4 has a couple of not insignificant hurdles.

The Issues with Certificates

There are a couple of obstacles in your way if you want to produce a valid publisher certificate for use in signing code.

  • For a smaller internal shop, going the "official" route of contacting one of the major certificate stores (Thawte, Verisign, et. al.) is overkill with a price tag.
  • Setting up a private Certificate Authority isn't that hard, but unless you're running Windows 2003, Enterprise Edition, you cannot customize certificate templates.
  • The settings on the Code Signing template marks the private key as "unexportable".

That last is the most significant problem. You see, if you cannot export your private key, you cannot export to a "pfx" file (aka "PKCS #12"). You could export a .cer file (public key only) and then convert that to an spc using cert2spc.exe but that leaves you with a file that pretty much anyone can use to sign code. There's a reason Visual Studio Help warns that cert2spc.exe is for testing only.

If I lost you in all the security acronyms, don't worry about it. The important thing to note is that a) non-pfx files don't need a password to use in signing assemblies and b) there's no easy way to create a non-developer created pfx file signed by your organization's CA.

How to Get Your CA to Issue an Exportable Certificate

There is, however, a loophole you can exploit to con your CA into giving you a Code Signing certificate that you can export into a valid .pfx file. I'll skip the setup stuff on the CA. It is important to make sure that your CA makes the Code Signing template available (it isn't by default). Making it available is pretty straightforward, so I won't go into that here.

The first thing you'll need to do is use makecert.exe to create both a private and public key. A basic commandline to do so would be:

makecert -n "CN=Text" -pe -b 12/01/2006 -e 12/01/2012 -sv c:\test.pvk c:\test.cer

You can hit the help file for other fields you might want to set (or use the -? and -! switches to get two lists of available options). This command will pop up a GUI prompt for your private key password. Note that I typoed "CN=Text". While I meant to make that "Test", it turns out to be a good way to illustrate what that value is so I decided to keep it in the following examples. Also note that "-pe" is what makes the private key exportable. After running this command, you'll have two files in your root directory. The pvk is the private key file and the .cer is the public key.

Next you use a Platform SDK tool called pvk2pfx.exe. This wasn't in my regular path so I had to do a search to find it. I'm guessing that most development machines will have it already. If not, it's available from Microsoft. Here's the command I needed:

"C:\Program Files\Microsoft SDKs\Windows\v6.0\Bin\pvk2pfx.exe" -pvk c:\test.pvk -spc c:\test.cer -pfx c:\test.pfx

Like makecert, this command will give you a password dialog for the private key. Note that even though the command switch is "spc", it'll accept a .cer file just fine. Now, you might think that we're done because we have a valid pfx file. The problem is that this pfx file is derived from a CA of "Root Agency". In order to get this into your internal CA, you're going to need to use your certificate manager. You'll likely need to Run certmgr.msc to get to it. Once there, head to the Personal|Certificates node. This will let you play with certificates on your current workstation.

Right-clicking on "Personal" gives you an "Import" option. Follow the prompts to pull your certificate in. It'll prompt you for the private key password. Once you do this, you'll see your new private key and probably an auto-imported "Root Agency".

Here's where we find the handy loophole. While the default value for allowing private key exporting on the Code Signing template is false, you can use your handy new certificate to request a duplicate. Right-click that key and select "Request Certificate with Same Key". You can also use "Renew Certificate with Same Key". The functional difference seems to me to be that Renew keeps your password while Request provides an empty one (which is nervous-making, but rectifiable using a number of different tools including Visual Studio once the certificate is exported).

In the Wizard that follows, make sure you select the Code Signing template. What you'll receive back is a certificate from your CA for code signing that includes a private key that is marked exportable. At this point, I delete both the "Root Agency" and "Text" certs in order to avoid future confusion.

Use the Right-click|Export command to export this certificate to a pfx file. The pfx file has everything you need to be able to create a .Net Framework code policy using "publisher" as the distinguishing characteristic to mark your code trusted. Once that policy is propagated to all the domain workstations, you're good to go. You'll need to use the resulting pfx file to sign the assemblies (once they're ready for release), but you knew that already :).

A Final Note

After I had a valid certificate for signing, I actually ended up using .Net's ClickOnce technology to deploy the project. I still needed a certificate to create a strong-named assembly, but a weaker or temp certificate would have been adequate for internal deployment. The more robust certificate will let me eliminate a security prompt the first time a user runs the application, though. Since that prompt has a big red exclamation point in it, I'm just as happy to eliminate it.

Tags: , , , , , , , ,

General IT

scruffylookingcatherder.com

Information

    Recent Posts

    Calendar

    <<  September 2010  >>
    MoTuWeThFrSaSu
    303112345
    6789101112
    13141516171819
    20212223242526
    27282930123
    45678910

    View posts in large calendar
    Disclaimer
    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2010 Scruffy-looking Cat Herder