2008年12月18日

[BizTalk]Fail to retrieve master secrets when accessing BizTalk port configuration

I got [Fail to retrieve master secrets] error message while trying to disable a receive port via BTS Administration console.

This error indicates that the SSO service shomhow could not retrieve the account information from SSO database, generally speaking, this should not cause by incorrect user identity you are using to access database since if that's the case, error message should state that SSO could not connect to SQL server.

In my case, I duplicate a new BTS VM and try to make it work in an AD environment and forgot to create a new SID for the duplicated machine.

To solve this issue,

  • open command prompt, change directory to %\Program Files%\Common Files\Enterprise Single Sign-on
  • execute the following command
    • ssoconfig -restoresecret <SecretKeyFileName>

2008年12月12日

[BizTalk]Clustering Host Instance and Calling Child Orchestration

I encounter a strange issue when calling child orchestration with parent orchestration's host instance is a clustered instance.

I have an orchestration calling a child orchestration, the child itself does only a simple web service invoke. The parent orchestration correlate a pack of messages via promoted property. This works fine in my development environment which is a stand alone BTS server.

Moving to production server which we clustered host instances for orchestration. When tries to pick up all messages in a package, I found that the call to child orchestration seems to be missed when receive the following messages after the first one
After serval tries, I realized that this occurs due to the child orchestration and its send/receive ports are not running under the same host instance the parent is running. So I change all orchestrations and their send/receive ports to same host instance the parent uses and the issue gone.

This is really strange since I thought BizTalk picks up messages from MsgBox, and hence BTS runtime should know which host the parent is running, it should be able to dispatch the message to same host the parent is running.

2008年11月20日

[BizTalk]Receive unexcepted message type in Orchestraion with SOAP Adapter

I was quite busy for the past few weeks, my wife gave birth to my second child, a lovely boy, we are now staying with my parents in law and has limited access to the internet. Which makes me diffcult to update this blog.

When invoking web service in orchestration via SOAP adapter, I got error states that unexcepted message type was received. The web service I am invoking has a return type of String, the event log shows that the orchestraion is expecting string, but WS.Response was received (or vice-versus, can't remember the detail).

This exception is thrown because when you create a SOAP port, BizTalk configure its receive pipeline as [Passthru pipeline]. A [Passthru] pipeline does not try to resolve message pass thru it, hence the SOAP response does not deserialize into string type.

To resolve this issue, simply change the receive pipeline of the SOAP port from [Passthru] to [XMLReceive].

2008年10月30日

[BizTalk]BizTalk Server 2006 R2 not compatible with 2008 Server Series

BizTalk Server 2006 R2 does not compatible with Windows Server 2008 and SQL Server 2008.

I setup BizTalk 2006 R2 on Windows Server 2008 (64bit) with SQL Server 2008(64 but), and tested with a simple publish-subscribe application, it seems work fine. But Microsoft states that the compability issue of BizTalk Server should be fixed on BizTalk Server 2009 which should be released around 2009 Q1.

I even try to user Visual Studio 2008 with BTS 2006 R2 (64 bit with Server 2008 64 bit,SQL 2008 64 bit), and sadly find out that VS2008 simply can not recognize BTS 2006 R2 Project file. This should also be fixed on BTS 2009.

2008年10月20日

[BizTalk][EDI]Repository was locked on host when validating EDI Schema

When Validating EDI Schema, you may get the following error:

Repository was locked on host[host name]


This occurs when compeif or xsd2edi runs and the EDI repository is locked in BTS EDI Database.

To solve this issue,

  1. connect to BizTalk Database server and execute the following SQL statement against BizTalkEDIDb
    USE BizTalkEDIDb


    GO


    UPDATE parame SET repolock=null


    GO




    This should effect only 1 row.




  2. Then open command prompt, execute “compeif” locate on BizTalk EDI subsystem folder.

2008年10月11日

[Dual-Boot] Vista & windows Server 2008

Things are not so diffcult as those internet users describes.

CPU:Intel Q9400
MB:ASUS P5QC
RAM:Transcend DDR2 800 - 2G * 4
Display:MSI 9500GT 512M
HD:WD 320GB * 2

First at all, download and update ASUS BIOS updates from ASUS website and update your BIOS to newest version. This is mandatory (I stuck here for almost one day), at this time, newest version should be 1409.

Then bootup with Vista install CD(I am installing Vista Ultimate 64 bit version), follow the instruction to setup Vista

After installation completed, reboot with Windows Server 2008 CD, following the wizard to complete server 2008 setup process.

Once the installation is done, reboot your machind and you’ll see both Vista & Windows 2008 are listed on bootup menu.

reference:

2008年10月1日

[.Net][ADSI]Get User Information from AD by SID

System.DirectoryService namespace provides many useful utilitu to communicate with AD, especially when you are querying object information. However, when querying AD object by objectSID, there’s a trick.

To query AD via System.DirectoryService namespace, first we have to create searcher object.

private static DirectorySearcher GetSearcher()


{


    DirectoryEntry de = new DirectoryEntry("LDAP://dc=mydomain,dc=com");


    DirectorySearcher ds = new DirectorySearcher(de);


    return ds;


}




Then to set query filter, in this case , I am searching objects by its sid.





ds.Filter = string.Format("(&(objectClass=user)(objectSid={0}))", ConvertByteToStringSid(binaryForm));




And to get correct SID string for query.





private static string ConvertByteToStringSid(Byte[] sidBytes)


{


    StringBuilder strSid = new StringBuilder();


 


    foreach (byte b in sidBytes)


    {


        strSid.Append("\\").Append(b.ToString("X2"));


    }


    return strSid.ToString();


}




We can not simply put filter like objectSid=S-1-5, to get this query work, we have to convert SID into format like \00\01\05…

2008年9月5日

[ASP.Net] Authentication ticket added manually by code could not be removed

When validating users in custom authentication module or aspx codes, we can manually add authentication ticket to the response like codes listed bellow:

FormsAuthenticationTicket fat = new FormsAuthenticationTicket(value, true, 10);


HttpCookie cookie = new HttpCookie(".AUTHFORM");


cookie.Value = FormsAuthentication.Encrypt(fat);


cookie.Expires = fat.Expiration;


HttpContext.Current.Response.Cookies.Add(cookie);




When trying to remove the ticket when its not needed, you may want do it by





FormsAuthentication.SignOut();


//or


HttpContext.Current.Response.Cookies.Remove(".AUTHFORM");




Although MSDN states that FormsAuthentication.SignOut() remove forms-authentication ticket, but you sadly realized that this seem not true when dealing with ticket created by codes.



So to solve this, we simply set the cookie's expiration to Now.





HttpContext.Current.Response.Cookies[FormsAuthentication.FormsCookieName].Expires = System.DateTime.Now;



This expires existing ticket.

2008年9月3日

[Remoting][.Net]The type initializer for 'System.Runtime.Remoting.Identity' threw an exception

When implementing a distributed system with .Net Remoting, sometimes we need to impersonate client users on server side(remoted object side), detail of how to setup the environment please refer to this post.

The system works fine until we move to staging environment. The most difference between testing env and staging env is that in staging env, our web are reside on web server and remoting system are in application server.(both in same domain)

When invoking remote method, I got this error:The type initializer for 'System.Runtime.Remoting.Identity' threw an exception.

This occurs due to the user which was impersonated does not have "Impersonate client after authenticated" & "Create Global Object" privillege. So to solve this we have to open "Local Security Setting" tool on remoting server(application server), open "Local Policies/User Rights Assignment", double click those 2 settings and add the user who will be impersonated.(see Microsoft Support Article)

When I done this, I got another error states that "Keyset is not defined", the most close situation I found on internet is this KBAlertz post, I did not check my CSP defination since I never modify them and I think they should not named with multi-byte characters by system default, so I when back to my source code and found that this exception was thrown when I tried to create a new AppDomain.

I remark those lines and the exception goes away.

 

Need to dig further about what have when wrong while creating AppDomain.

2008年8月8日

[ASP.Net] Download File & Open File on browser

There are times you need uses to open files on browser rather than to download and save them to the disk. To do this we need to specify HTTP header(Content-Deposition)

To enforce download dialog,

Response.AddHeader("Content-Disposition", "attachment; filename=" + fn);
To open on browser,
Response.AddHeader("Content-Disposition", "inline; filename=" + fn);


 

2008年7月31日

[IIS][ASP.Net][Web Service][WSE] Web service and Forms authentication - 2

Second solution for Forms Authentication with web service.

  1. Create a new project.
  2. Create a new class implements IHttpModule interface, attach HttpApplication::AuthenticateRequest event in Init() function -
  3. context.AuthenticateRequest += new EventHandler(context_AuthenticateRequest);



  4. In context_AuthenticateRequest(), we check if this is a request to our secured web service, if so, we issue a HTTP 401 to the client, this will ask client to request web service again with WWW-Authentication header present if client has set PreAuthenticate to true.(and if not, client end up with a HTTP 401 error)


  5. private bool IsAuthenticationRequired(HttpApplication app)
    {
    return app.Context.Request.Url.AbsolutePath.EndsWith("someservice.asmx", StringComparison.OrdinalIgnoreCase);
    }


    private void context_AuthenticateRequest(object sender, EventArgs e){
    if(!IsAuthenticationRequired((HttpApplication)sender))
    return;
    if (string.IsNullOrEmpty(httpApplication.Request.Headers["Authorization"]))
    {
    //client have to make a Basic authorization communication with server
    requestBasicAuthentication(httpApplication);//Request authorization
    }else{//...Authenticate user here...}
    }


    private void requestBasicAuthentication(HttpApplication httpApplication)
    {
    httpApplication.Response.AppendHeader(
    "WWW-Authenticate",
    string.Format("Basic realm=\"{0}\"",
    "my service test"));
    httpApplication.Response.StatusCode = 401;
    httpApplication.CompleteRequest();
    }



  6. Now we have to make this request authenticated, since our web site is using Forms Authentication, we call Membership.ValidateUser() to validate the incoming request as web site do. If the user is validated, don't forget to set user identity to the request.


  7. //...
    //check to see if is Basic authentication we are facing
    string sToken = httpApplication.Request.Headers["Authorization"];
    if (sToken.StartsWith("Basic", StringComparison.OrdinalIgnoreCase))
    {
    //Basic ahthorization
    validateBasicAuthentication(httpApplication, sToken);
    }
    //...
    private void validateBasicAuthentication(HttpApplication httpApplication, string token)
    {
    string credentialString = token.Substring(6);
    byte[] buffer = Convert.FromBase64String(credentialString);
    credentialString = Encoding.Default.GetString(buffer);
    string[] frags = credentialString.Split(new char[] { ':' }, 2);
    if (!System.Web.Security.Membership.ValidateUser(frags[0], frags[1]))
    DenyAccess(httpApplication);//bad identity
    else{
    //This is required so that web application can get user identity via User property
    SetPrinciple(httpApplication, frags[0]);
    }
    }



  8. To deny an acccess, simply issue a HTTP 401 response, and to set principal, we modify current context's Principal property.


  9. private void SetPrinciple(HttpApplication httpApplication, string userName)
    {
    RolePrincipal principal = new RolePrincipal(new System.Web.Security.FormsIdentity(
    new FormsAuthenticationTicket(userName, false, 10)
    ));
    httpApplication.Context.User = principal;
    }



  10. Now we have to make some changes to web.config, first, ofcourse, we have to register our http module.


  11.     <httpModules>
    <add name="mymodule" type="MyModule,MyAuthention"></add>
    </httpModules>



  12. This register our http module, but it's not just enough, because by default, FormsAuthentication module fires before modules listed under <httpModules> element, and if we have to authenticate incoming request before all other authentication modules. To do this, we can simply remove FormsAuthentication module by adding a <remove name="FormsAuthentication"/> before the <add> element.


  13. <remove name="FormsAuthentication"></remove>
    <add name="mymodule" type="MyModule,MyAuthention"></add>



  14. But, remember, our module only authenticate request to web services, not classic web pages, so we must add FormsAuthentication back again.


  15. <remove name="FormsAuthentication"></remove>
    <add name="mymodule" type="MyModule,MyAuthention"></add>
    <add name="FormsAuthenticationOld" type="System.Web.Security.FormsAuthenticationModule"/>



  16. And here's how client calls web service


  17. ws.CookieContainer = cc;//cookie container
    //set PreAuthenticate = true, so when a HTTP 401 received,
    //client will issue another request with authentication headers
    ws.PreAuthenticate = true;

    ws.Credentials = new System.Net.NetworkCredential(user, password);





2008年7月25日

[IIS][ASP.Net][Web Service][WSE] Web service and Forms authentication

We have a ASP.Net 2.0 web site secured by Forms authentication with custom membership provider & role manager, within this web site, we have a web service exposed as an API. We want this web service also be secured with same mechanism.

I thought of adding Credentials to web service proxy class, but this fails since Credentials should only work with Windows authentication.

Then I thought of maybe <location/> element helps since this element enables you have different configuration settings with different urls. and this also failed, because you can't write a web.config like this:

  <location path="." allowOverride="true" inheritInChildApplications="true">
<system.web>
<authentication mode="Forms">
<forms loginUrl="login.aspx" name=".ASPXFORMSAUTH">
</forms>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
<location path="svc.asmx">
<system.web>
<forms loginUrl="svc.asmx?op=Logon" name=".ASPXFORMSAUTH">
</forms>
</system.web>
</location>


And this fails still because <authentication/> is not a overridable element in web.config, so that you can not specify 2 different login pages in same web site.



Finally, Andrew Arnott's Blog saves me, he has the same issue I have, follow his instruction, we are now able to use same Membership provider/Role manager to authenticate both web site & web service.



Bellow is a summary:




  1. Install WSE 3.0


  2. On your web project, open up WSE 3.0 property page

    1. Check both [Enable this project for web services Enhancements] and [Enable Microsoft web services Enhacement Soap protocol Factory]


    2. Under [Security] tab, add a custom token manager


    3. Enable policy, name your new policy, this policy name will be used both server side and client side, so don't miss it.




  3. Click OK to complete server setting.

    1. a wse3policyCache.config file will be generated




  4. Enable your web site's Membership/RoleManager if they are not enabled yet.


  5. Modify wse3policyCache.config, allow specificed roles to access this web service(for me,"User" role are allowed), your wse3policyCache.config should look like this
    <policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
    <extensions>
    <extension name="usernameOverTransportSecurity" type="Microsoft.Web.Services3.Design.UsernameOverTransportAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    <extension name="requireActionHeader" type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </extensions>
    <policy name="usernameTokenSecurity">
    <authorization>
    <allow role="User"/>
    <deny role="*"/>
    </authorization>
    <usernameOverTransportSecurity />
    <requireActionHeader />
    </policy>
    </policies>



  6. Add a custom token manager in APP_CODE folder, code listed bellow:
    using System.Xml;
    using System.Web.Security;
    using System.Security.Permissions;
    using System.Security.Principal;
    using Microsoft.Web.Services3.Security;
    using Microsoft.Web.Services3.Security.Tokens;

    [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    public class CustomUsernameTokenManager : UsernameTokenManager
    {
    //codes omitted.
    protected override string AuthenticateToken(UsernameToken token)
    {
    bool validCredentials = Membership.ValidateUser(token.Username, token.Password);
    if (!validCredentials) throw new UnauthorizedAccessException();

    GenericIdentity identity = new GenericIdentity(token.Username);
    GenericPrincipal principal = new GenericPrincipal(identity, Roles.GetRolesForUser(token.Username));
    token.Principal = principal;

    return token.Password;
    }
    }



  7. Modify <microsoft.web.services3> section in your web site's web.config, should look like this:
      <microsoft.web.services3>
    <security>
    <securityTokenManager>
    <add
    type="CustomUsernameTokenManager, __code"
    namespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" localName="UsernameToken" />
    </securityTokenManager>
    </security>
    <policy fileName="wse3policyCache.config" />
    </microsoft.web.services3>




  8. Modify web.config to allow client to call your web service


      <location path="svc.asmx">
    <system.web>
    <authorization>
    <allow users="*"></allow>
    </authorization>
    </system.web>
    </location>




Now it's time to configure your client application.





    1. open WSE property page on client project


      1. Check [Enable this project for Web Service Enhancements]


      2. Enable Policy, add a new policy with exactly same name you named your server policy, in our case, should be "usernameTokenSecurity"

        1. A wse3policyCache.config file will be generated




      3. Update your web reference


      4. Modify your client code as follow:
              private GetService CreateWebService()
        {
        if (ws == null)
        ws = new svcWse();
        ws = new svcWse();

        UsernameToken userName = new UsernameToken(user, password,PasswordOption.SendPlainText);
        ws.SetClientCredential(userName);
        ws.SetPolicy("usernameTokenSecurity");
        return ws;
        }
        public String[] GetItemList()
        {
        return CreateWebService().GetItemList();
        }







N

2008年7月10日

[BizTalk] BTS stop responding and you got TDDS lock timeout error in event log

My BTS 2006 stop processing incoming messages with the following event log entry.

Event Type:    Error
Event Source: BAM EventBus Service
Event Category: None
Event ID: 25
Date: 7/10/2008
Time: 5:51:49 PM
User: N/A
Computer: [BTSSVC]


Description:
Either another TDDS is processing the same
data or there is an orphaned session in SQL
server holding TDDS lock.Timeout expired.
The timeout period elapsed prior to
completion of the operation or the server
is not responding.
SQLServer: [SQLSVRNAME],
Database: BAMPrimaryImport.


For more information
, see Help and Support Center at
http://go.microsoft.com/fwlink/events.asp.


If you are running BTS 2004, then simply following this KB article (Microsoft KB897653).



If you are running BTS 2006, TIHO's blog has detail information about this error and how to fix it.



Simply speaking, if this happens on BTS2006 server, then one of the following must be solved:




  1. There are orphanded sessions.

    1. Orphanded sessions are those clients that is not able to free their network connection when terminated.


    2. This article shows how to identify if you are running into orphanded session problems and how to solve it.




  2. You have permission issues

    1. The account under which TDDS(Tracking Data Decode Service) must have execute permissions for the following stored procedures in BTS Msg db:TDDS_RedisterTDDSAccess & TDDS_GetNumTrackingPartitions.


    2. The same account must also have execute permission to TDDS_Lock stored procedure in DTA/HAT & BAM Primary Import Databases.


        1. To check and solve permission issues, first connect to BTS Msg DB with same credentials TDDS is running under. then try to execute the following sql statement:
          use [BizTalkMsgBoxDb]

          DECLARE @RC int
          DECLARE @retVal int
          EXEC @RC =
          [dbo].[TDDS_RegisterTDDSAccess]
          @retVal OUTPUT
          SELECT @RC
          GO

          DECLARE @RC int
          DECLARE @nPartitions tinyint
          EXEC @RC =
          [dbo].[TDDS_GetNumTrackingPartitions]
          @nPartitions OUTPUT
          SELECT @RC
          GO





      1. And the following against BTS DTA & BAM Primary Import databases:



        use [BAMPrimaryImport].
        DECLARE @RC int
        DECLARE @resource nvarchar(128)
        DECLARE @milisecTimeout int
        DECLARE @retVal int
        SELECT @resource = N'Foo'
        SELECT @milisecTimeout = 5000
        EXEC @RC =
        [dbo].[TDDS_Lock]
        @resource,
        @milisecTimeout,
        @retVal OUTPUT
        SELECT @retVal
        SELECT @RC
        GO









If you got error messages state you are lack of permissions executing those sql statement against BTS MsgDB & DTA/BAM DBs, try to grant execute permission to the account you are connecting to SQL server until no more error messages are shown.

2008年6月16日

[IIS] How to install ASP.Net 3.5 onto IIS 6 ?

You don't need to.

ASP.Net 3.5 is basically an extension of ASP.Net 2.0, so just register ASP.Net 2.0 to IIS 6 and you are ready to run your ASP.Net 3.5 application on IIS 6.

But there do have some configuration settings you might need to know if you are running you applicaion on web server without VS2008 installed.

If you create your site with VS2008. then these settings are created by VS, but you may need to add the following section to your web.config to make your site compiled with ASP.Net 3.5 if you are modifying an existing site.

<system.codedom> 
<compilers><compiler language="c#;cs;csharp" extension=".cs" compilerOptions="/warnaserror-" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<providerOption name="CompilerVersion" value="v3.5"/></compiler>
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" compilerOptions="/optioninfer+" type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"><providerOption name="CompilerVersion" value="v3.5"/>
</compiler></compilers>
</system.codedom>



Also, your assembly settings should be changed.



<compilation debug="true">
<assemblies>
<add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</assemblies>
</compilation>

2008年6月13日

[SQL Express]How to change LogonMode and sa password

  1. 1. Open Regedit.
  2. 2. Check if [HKLM\Software\Microsoft\Microsoft SQL Server\MSSQL.1\MSSQLServer\LoginMode] is set to 1(Windows Mode) or 2(Mix Mode)
  3. 3. Modify the registry key to 2.
  4. 4. Open command prompt, change to C:\Program Files\Microsoft SQL Server\90\Tools\Binn
  5. 5. Execute osql -S [ServerName]\[InstanceName] -E
  6. 6. Under OSQL prompt, type each of the following statement and press Enter.
    sp_password @old = null, @new = 'complexpwd', @loginame ='sa'


    go




  7. 7. Restart SQL Service




reference:http://support.microsoft.com/kb/322336


2008年6月6日

[.Net][Remoting]Impersonate client user on Remoting server

Sometimes you need to simulate client user on server operations, with .Net Remoting, this can be done in simple steps.

On the server side, we have to enable security communication and to set impersonate level, this can be done by adding configuration settings in application config file:

<channel ref="tcp" port="8888" secure="true" impersonate="true" authenticationMode="ImpersonateCallers"/>

  • impersonate="true" to enable impersonation on threads
  • authenticationMode="ImpersonateCallers" to impersonate the caller, which impersonate client user before calling remoted object's methods
  • secure="true" to enable security options

On the client sider, application should comply server's rules

<channel ref="tcp"
secure="true"
tokenImpersonationLevel="impersonation">
<clientProviders>
  • secure="true" to enable client security options
  • tokenImpersonationLevel="impersonation" to enable client side impersonation, this property is same with server's impersonate property

When you server starts, do enable security option in your code:

System.Runtime.Remoting.RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,true);

On client side application, also configure remoting service via config file with secure enabled like the above code sample.

The above sample illustrate NTLM scenario, with Kerberos, you'll have to add a property spn="Service/Domain" in your client configuration file.

reference:

  1. http://www.leastprivilege.com/
  2. How to add CIA to .Net Remoting
  3. Remoting config file format

2008年6月5日

[.Net] SelectNodes case insensitively with .Net Xml DOM

The Microsoft .Net Framework provides interfaces that you can use them to implement your own extended functions to work in XPath expressions, and here are what you ought to know when you want to perform a case-insensitive search.

First is to write your own XslContext class, to do  this, create a class inherits from System.Xml.Xsl.XslContext class, and implement its abstract methods.

public class XmlExtendedContext:XsltContext
{
public override IXsltContextFunction ResolveFunction
(string prefix,
string name,
XPathResultType[] ArgTypes)
{
IXsltContextFunction resolvedFunction = null;
if (this.LookupNamespace(prefix) == EqualsFunction.Namespace &&
name == EqualsFunction.FunctionName)
resolvedFunction = new EqualsFunction();
return resolvedFunction;
}
}


The ResolveFunction() method resolves custom functions in XPath. So we have to write another class EqualsFunction to actually perform the function.





public class EqualsFunction{
public const string Namespace =
"http://myextensions.xml";
public const string FunctionName
= "equals";

private XPathResultType[] m_argTypes =
new XPathResultType[] {
XPathResultType.Any,
XPathResultType.Any };

#region IXsltContextFunction Members
public XPathResultType[] ArgTypes
{get{return m_argTypes;}}
private string GetArgs(object arg)
{
string stringValue;
if (arg is string)
stringValue = (string)(arg);
else if (arg is XPathNodeIterator)
{
XPathNodeIterator i =
(XPathNodeIterator)arg;
if (i.MoveNext() == true)
{
XPathNavigator navigator = i.Current;
stringValue = navigator.ToString();
}
else
throw new ArgumentNullException();
}
else
throw new ArgumentNullException();
return stringValue;
}
public object Invoke(
XsltContext xsltContext,
object[] args,
XPathNavigator docContext)
{
if (args.Length != 2)
throw new ArgumentNullException();
string argument1 = GetArgs(args[0]);
string argument2 = GetArgs(args[1]);
bool result = string.Equals( argument1, argument2, StringComparison.CurrentCultureIgnoreCase);
return result;
}
#endregion
}



And to use newly created function in your code:



//Create custom Context
XmlExtendedContext ctx = new XmlExtendedContext(doc.NameTable);

//Prepare namespace manager
ctx.AddNamespace("s", XmlExtendedContext.EqualsFunction.Namespace);

//perform the search
return doc.SelectSingleNode"//*/child[s:equals(@Name,\"TEST\")]",ctx);













2008年5月30日

[.Net]More than one exclusive group is not allowed

I have a ASP.Net web application deploy on 2 load balaced web servers with its source code stored on shared folder of file server.

I keep getting [more than one exclusive group is not allowed] while trying to browse my web site.

After digging into event log, I also found Event ID:1310 with Event Code:3008 were logged on Event log

This exception is thrown due to mCAS (code access security) exclusive policy were set again SAME code group twice, so that .Net could not decide which policy should be applied.

We can fix that in a simple way:

run

[%WINDOWS%\Microsoft.Net\Framework\v2.0.50727\caspol - rg [%group_name_or_lable%]

to remove duplicated policy.

2008年4月15日

[BizTalk] SQL Adapter 0x8000405 error

When querying database via SQL adapter, I got a 0x8000405 error on event log

SQL Adapter send/receive Xml data, when creating SQL request/response xml schema, we need to add "for xml auto,xmldata" in your stored procedule so the wizard can have xml schema returned from stored procedule.

After schema is generated, you will need to remove "xmldata" from your stored procedule, or 0x800405 error will be logged, and your query failed with the following error description "Streaming not supported over multiple column result".

2008年4月9日

[.Net][Remoting] Remoting with TCP channel and NLB

.Net framework 1.1 has some problem with TCP channel in NLB.
In .Net framework 2.0, TCP channel has been enhenced to support real world network environment.
The following configuration settings are useful when configuring TCP Remoting with NLB

<channels>
   <channel port="xxx" ref="tcp" socketcachetimeout="0" socketcachepolicy="absoluteTimeout" />
</channels>

Here is what you need to know about Microsoft supports for .Net Remoting with NLB.

2008年3月26日

[SQL2005][SSIS]DTS_E_OLEDBERROR when executing SSIS package

When executing SSIS package imports data from Excel file into SQL 2005 Database
I get the following error

Error 0xc0202009: Data Flow Task: SSIS Error Code DTS_E_OLEDBERROR.  An OLE DB error has occurred. Error code: 0x80040E21.
An OLE DB record is available.  Source: "Microsoft SQL Native Client"  Hresult: 0x80040E21  Description: "Multiple-step OLE DB operation generated errors. Check each OLE DB status value, if available. No work was done.".
(SQL Server Import and Export Wizard)
Error 0xc0202025: Data Flow Task: Cannot create an OLE DB accessor. Verify that the column metadata is valid.
(SQL Server Import and Export Wizard)
Error 0xc004701a: Data Flow Task: component "Destination - Employee" (205) failed the pre-execute phase and returned error code 0xC0202025.
(SQL Server Import and Export Wizard)

SQL 2005 checks data type before actually imports data from source to destination
For example, an Access column with MEMO data type is limit to 65536 bytes, which is greater than a SQL nvarchar's limitation.
This generates a DTS_E_OLEDBERROR when executing SSIS package.


To fix this behavior, map destination data column to a different data type, or increase its length(for example, nvarchar(50) to nvarchar(max))

Blog Archive

About Me