- Make sure the COM DLL (compiled) is in TFS as well.
- Manually edit your VS project file to change the relevant COMReference elements to COMFileReference elements as follows:
Monday, October 15, 2012
DLL Hell and TFS Builds
Saturday, May 19, 2012
NuGet Package: Twitter Bootstrap
Twitter kindly created Bootstrap, a collection of CSS and JS code to speed up the creation of standards friendly web sites.
Bootstrap on NuGet
Failing to find a handy NuGet package, I rolled my own NuGet package for Twitter Bootstrap (bootstrap 2.0.2), relying on dotless for .less support.
I hope this helps someone out there.
Please post feedback in the comments.
Monday, February 14, 2011
Kerberos Security Checklists
Security ala Microsoft
Security – authentication and authorization – is a basic need of intranet applications and a great amount of infrastructure is geared toward enabling security features seamlessly.
Denizens of the planet Microsoft store their intranet user accounts and security groups in Active Directory. Then they configure their web applications for Windows Integrated Security, a.k.a. Single Sign On, whereby the user’s NT username – already authenticated when logging into the client machine – is passed to the web server along with the Http Request and used to authenticate and authorize the user for the application, by means of Kerberos authentication.
The Dreaded Double-Hop Error
One particularly nefarious error looks as follows:
Unauthorized (null)
orAnonymous logon (null)
Causes include:
- Bad server configuration
- Bad network configuration (Service Principal Name - SPN; speak to your network admin)
- Bad client browser configuration
- Client login ticket has expired
Solution Checklists
Checklist: Server
- Connection Pool of site runs under Network Service identity
- Windows Authentication enabled for site
- Impersonation enabled for site
Checklist: Client
- Windows Integrated Authentication enabled (Tools > Internet Options > Advanced)
- Check "Bypass proxy server for local addresses" (Tools > Internet Options > Connections > LAN Settings)
- Allow "Automatic logon only in Intranet zone" (Tools > Internet Options > Connections > Security > Local Intranet > Custom Level)
- Add intranet domain (*.mydomain.com) to list "web sites" (Tools > Internet Options > Connections > Security > Local Intranet > Sites > Advanced > Web Sites )
If the user has successfully accessed the site in the past, it may be a matter of refreshing the login token:
- Close-reopen browser (IE7+)
- Right click browser icon > Run as... > enter credentials (IE6)
- When all else fails... REBOOT
Wednesday, February 9, 2011
Synchronous Ajax with Microsoft
Ajax Without the A
Microsoft Ajax makes it easy for us to call Web Service methods and code-behind Page Methods from our client JavaScript code. However, the process is always asynchronous (the A in Ajax) and requires the use of callback functions.What about synchronous calls? Sometimes, you want to halt execution until the results arrive – for purposes of data validation, for instance.
The bad news: synchronous calls are not supported out-of-the-box.
The good news: you can work synchronously without having to work with XmlHttpRequest or switch to jQuery.
Synchronous Steps
Step 1Add scripts to your page for the XmlHttpSyncExecutor and ExecuteSynchronously wrapper method provided thanks to Ricardo Peres.
Step 2
Make sure your Web Service has the right attributes:
[WebService]
[System.Web.Script.Services.ScriptService(ResponseFormat = ResponseFormat.Json)]
public class MyWebService: System.Web.Services.WebService
{
[WebMethod]
[System.Web.Script.Services.ScriptMethod]
public string MyWebMethod(int id)
{
return "test:" + id.ToString();
}
}Step 3Call the web service using the ExecuteSynchronously wrapper function in your client-side JavaScript:
var res = ExecuteSynchronously('<%=Request.ApplicationPath %>/WebService/MyWebService.asmx',
'MyWebMethod',
{ 'id': 100 });
alert(res.d);Note two things:- Pass parameters as a JSON object (third parameter of the ExecuteSynchronously function)
- The JSON result is stored in property d of the return value
Thursday, December 30, 2010
Integrated Windows Authentication and FireFox
"That should be easy. You develop cross-browser anyway. Right?"Well, yes and no.
Your Html, Css and JavaScript are only part of the picture.
Browser settings are another creature altogether, and when you're working with Kerberos authentication, browser settings are critical to:
- pass the users credentials without prompting him or her to sign in (single sign-on) and
- allow impersonation and delegation of users credentials from the web server to the database server (double hop).
FireFox Settings - Cheat Sheet
There are 5 settings you need to change, all accessible when you type about:config in the address bar:
setting: network.negotiate-auth.delegation-uris
value: mySite.com,myotherSite.com
setting: network.negotiate-auth.trusted-uris
value: mySite.com,myotherSite.com
setting: network.automatic-ntlm-auth.trusted-uris
value: mySite.com,myotherSite.com
setting: network.automatic-ntlm-auth.allow-proxies
value:true
setting: network.negotiate-auth.allow-proxies
value: true
Piece of cake.
Now for the hard part: figuring out how to change the FireFox settings for your thousands of users...
Wednesday, October 6, 2010
Outlook 2010 Add-In Issue: Closing “Send Using Email” Window
Scenario:
Add-In for Outlook performs an action in the Application_ItemSend handler for outgoing email.
Add-In works for Outlook 2007, but in Outlook 2010 a strange side-effect occurs. When using the “Send Using Email” feature of Word 2010, the email sends but the modal email window stays open! The user has to close it manually.
More good news: Calling the Close(..) method of the inspector throws an error.
Solution:
There is no elegant solution; you have to resort to DLL Imports.
Add the DLL Imports for finding a window and sending it a message:
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool PostMessage(IntPtr hWnd, uint wMsg, IntPtr wParam, IntPtr lParam);
const int WM_CLOSE = 0x10;Then, in call this in your code, making sure to clean up any COM object references that need to be released (but NOT the EmailItem reference):
void Application_ItemSend(object Item, ref bool Cancel)
{
if (Item is Outlook.MailItem)
{
Outlook.MailItem mail = Item as Outlook.MailItem;
Outlook.Inspector inspector = null;
if (null != mail)
{
>
try
{
inspector = mail.GetInspector;
if (null != inspector)
{
//TODO: your add-in magic!
}
}
finally
{
if (null != inspector)
{
IntPtr _inspHwnd = FindWindow("rctrl_renwnd32", inspector.Caption);
bool retVal = PostMessage(_inspHwnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
Marshal.ReleaseComObject(inspector);
}
}
}
}
}
Thanks to Ken Slovak and Andrei Smolin for their valuable input…
Monday, July 12, 2010
SSIS and WCF – The Devil in the Wsdl
I want to elaborate on a fix that wasn't so obvious to me...
The plan seemed simple enough. Current Application requires email reports to sent, some from the web GUI, others according to certain conditions and schedules. Instead of duplicating the report logic in multiple places, let's place it all in one WCF Service application (sending the reports offline via MSMQ) and then call the service from both the web GUI and an SSIS job that runs according to the conditions and schedules.
Not too much to ask, right?
Enter SSIS.
Web Service Task
SSIS offers a task for calling web services - you guessed it: the Web Service Task - which claims to support WCF too so long as the WCF uses Basic Http Binding.
So you add the Web Service Task, configure the Wsdl url and then...error:
Item has already been added. Key in dictionary: 'anyType' Key being added: 'anyType'
Some friendly souls encountered this error before and offered sage advice here and here but the solution requires some spelling out.
The Wsdl needs to contain type definitions for the service methods and data contracts etc. These are split over a number of xsd files, all referenced in the Wsdl:
Here’s the catch: Wcf generates Wsdl that creates circular references within the xsd files.
Here’s the content of Xsd2:
Note that Xsd2 refers to Xsd3 and Xsd1 even though they are already referenced in the Wsdl.
The result: SSIS in Visual Studio blindly builds a list of valid types based on these Xsd files and thus tries to add some types twice – and fails on validation.
This validation is usually a good thing, but flags Wcf-generated Wsdl content as a false positive.
The Solution
The way out of this mess?
- Look through the Xsd references in your Wsdl
- Peek at the Xsd files too (copy the urls to your browser of choice)
- Eliminate from the Wsdl file all references to Xsd files already referenced in earlier Xsd files.
In my case this meant deleting all the Xsd references from the Wsdl except for the first one.
[The irony, of course, is that I encountered a row of other issues – setting the Input and Output parameters for the Task, for starters – and decided to ditch the Web Service Task in favor of a Execute Script Task, which uses an old-fashioned web service reference in the script editor.
So much for that…]
