Biztalk insists "This Assembler cannot retrieve a document specification using this type" but I am confident it is wrong - biztalk

First and foremost I would like to draw your attention to this:
That's because I have been to all of those links. I've tried those suggestions (I'll get into that). I've even been to the second page of Google.
I'm working on an existing setup which I think I might have broke when I imported bindings from another server without backing up the current bindings. When the imported bindings failed I had nothing to revert to. My bad, I know you are always supposed to back things up but this time I did not. Anyways, or maybe the bindings have nothing to do with any of it, I really don't know.
When executing a stored procedure it says This Assembler cannot retrieve a document specification using this type: "http://Foo.Bar.SQLIO#A_sqli". Now the namespace and database server are covered up here but trust me, they are correct.
Now this is where people will insist the only possible reason this ever happens is either:
There is a namespace collision and you have to explicitly specify the strong name.
The assembly is not in the GAC.
So let's talk about 1 first... So I'm gonna grab the SchemaStrongName, AssemblyName AKA Foo.Bar.SQLIO, Foo.Bar, Version=1.5.0.0, Culture=neutral, PublicKeyToken=585b3f1e468ca8f5 and paste that into the DocumentSpecNames of the XMLTransmit Send pipeline on the Send Port.
Now I rerun and the namespace ambiguity/collision/problems should be gone but they are not. Instead I get a new error which basically says the same thing.
Okay but I am pretty sure that the schema exists exactly once and the dll is deployed to the GAC correctly. Why? Several reasons:
First, the schema is listed only once. .
I can further validate that by programmatically referencing the assembly in a standalone console app, and printing the schema to a file.
static void Main(string[] args)
{
var x = new Foo.Bar.SQLIO();
Console.WriteLine(x.XmlContent);
File.WriteAllText(#"C:\Users\CoolSean\Desktop\OUT-OF-ASSEMBLY.xsd", x.XmlContent);
}
As for the dll being in the GAC I can verify that with gacutil -l Foo.Bar and it is there. If I do gacutil -u Foo.Bar and restart the host instances it fails because it can't find the assembly, meaning I am poking at the right assembly. It does exist and it does contain the schema and even the BizTalkMgmtDb database knows about it.
What can I do to run this down? I've got a working copy of this BizTalk application on another server and I setup a SQL Profiler trace on the broken box and the working box. The database calls are identical right up until the broken box starts logging errors about how it can't find that schema. idk man. What if I recompile Foo.Bar.dll such that it writes to a file any time anyone calls any of its methods. That would tell me ....something. Maybe. Probably not. I'm out of ideas.

Related

Where does BizTalk keep dlls?

I am having some trouble with BizTalk saying a schema doesn't exist when it does exist.
I can see it in the BizTalkMgmtDb using
select * from bt_documentspec where msgtype like '%myschema%'
I can see it in the BizTalk Server Administration Console > <All Artifacts> > Schemas > My Schema.
This paragraph is optional. I'm only including it so you know I already tried the answer you get when you google this problem.
The exact error message I get is something like "This Assembler cannot retrieve a document specification using this type" which if you google that tells you the schema is either not deployed or the root element you're using exists in two separate namespaces so you should supply a DocSpecName on the SendPorts XMLTransmit 1 2.
I've also tried reinstalling the dll that contains the problem schema into the GAC as per the answer to this question. That didn't work either but now I have more questions anyways.
if I do gacutil -l none of my assemblies are listed there.
So I was wondering what does this even do?
Because those assemblies are not listed under gacutil -l. Also when you look at those assemblies
it shows a source location and a destination location.
Why? Why not just THE location? I can't even find %BTAD_InstallDir% on my computer so there are a minimum of 4 possible locations where this schema dll might be.
source location
destination location (%BTAD_InstallDir%)
"the GAC"
wherever it actually is because there doesn't seem to be a %BTAD_InstallDir%.
So if I want to "update the GAC" to make sure this schema is there how do I do that? What dll is BizTalk ACTUALLY using? The one in %BTAD_InstallDir% or the one in the GAC?
BizTalk 2010.
It has nothing to do with where the DLL is, it has to do with the fact that either
The XML payload namespace and root node does not match any schema
You have two or more schemas with exactly the same namespace and root node that match.
If you don't have any namespace on the XML, then it will try and match on Root node only, but again if you have more than one schema with the same root node, it will fail.
What you need to do is look at the suspended message and look at it's context properties and see what it's Message Type is, and compare that against the schema in BizTalk. There should be exactly one that matches.
vs
But to answer your question,
The source location is usually just the path of where the DLL was when it was initially imported in Dev.
the %BTAD_InstallDir% is the directory you chose when importing a MSI, the default location is C:\Program Files (x86)\Generated by BizTalk. However that is just where it puts it initially
Yes, in the end the actual one it uses will be in the GAC, which is under C:\Windows\Microsoft.NET\assembly\GAC_MSIL
Note: If the DLL has been previously been deployed and you are deploying a new one then make sure you restart the host instances afterwards, as it will cache DLLs in memory for a period.

Could not load file or assembly when trying to remove/delete Resource/Application

I have a Biztalk application that is basically a housing for a schema that other applications are using. I now want to remove this application, but am unable to from the BizTalk Server Admin Console, when I right-click --> Remove I get an error that says
Could not load file or assembly <assembly_name>.dll or one of its dependencies. The system cannot find the path specified (mscorlib)
followed by:
The system cannot find the path specified (Exception from HRESULT: 0x80070003)
So I go to remove the assembly from the Application and get the exact same error. I remove all references to it in other biztalk resources and still the same error when trying to delete the application or resource. I did notice that in the Modify Resouces dialog of referencing assemblies, this rogue assembly is listed as a dependency status of Not Found.
The strange thing is, when Messages come through, the resources which depend on the rogue assembly, still work fine and no errors are thrown (despite them using components of the assembly which shows as Not Found).
I have made sure to check the GAC and the assembly is loaded to it.
So now I have to ask:
where is Biztalk actually looking for this assembly?
is there a way I can just force a deletion of this application?
why does it care if the assembly is not found, when I'm trying to delete it?
why does it show as Not Found, yet still work?
Thanks.
I think the key is "or one of its dependencies." If it's a dependency it may be using the standard windows mechanism for finding a dll. It searches the current directory and the windows directory for them.
"where is Biztalk actually looking for this assembly?"
Look in the 'resources' section of your application in the biztalk management console. It shows a column with the location of the assembly.
I'd stop all the host instances/orchestrations, and then unload all your stuff from the GAC - if messages are actually still going through then stuff is still loaded that is using your schema.

Debugging SDL Tridion 2011 Custom Resolvers and the GetListPublishItems() method

In one of my C# Template Building Blocks I have the following line of code
publication.GetListPublishItems(uriTarget, false, false,
TDSDefinesInterop.ListColumnFilter.XMLListDefault, listRowFilter);
Before implementing a Custom Resolver, this code executed very quickly. Now that my resolver is implemented for the Publication ItemType the code executes really slowly. From this I conclude that the new Resolver is being called behind the scenes by the GetListPublishItems() method (which makes sense). I assume I need to modify the resolver somehow. However I can't seem to hit a break point in my resolver when the method is called.
I normally attach to the 'TcmTemplateDebugHost' when debugging a template or directly to the publisher process when debugging the resolver. My Resolver only seems to get hit when I first press Publish and not when the GetListPublishItems() method is called.
So this question is twofold:
Do Resolvers get called when the GetListPublishItems() method is used?
Assuming they are called, which process should I attach to when I need to debug it in this scenario?
I don't know for certain, but I can't imagine a sane scenario where a custom resolver wouldn't be involved in GetListPublishItems(). Your evidence seems to back this up, but of course, if we can answer the second part of your question, we'll know it for certain.
I imagine that any normal assumptions you've made about the hosting process are probably correct, so for example, if you are invoking your template during a publish, then the TcmPublisher will be the process. Alternatively, if you were to open up the publish dialog for the publication in the GUI and hit "Show Items To Publish", then it would probably be the COM Surrogate process (dllhost.exe)... and so on. One way to find out for sure, though, is to use Sysinternals Process Explorer, which has a very handy feature that will allow you to search for which processes have a given dll loaded. (Look in the Find menu)
One likely cause for a breakpoint failing to bite is that Visual Studio isn't able to load the symbols correctly. When you're debugging a template building block, Tridion explicitly loads the symbols from a known location, which you can configure (tridion.templating/debugging/#pdbdirectory in the CM config), which is where the template uploader places the PDBs. When the publisher process loads the custom resolver, I doubt if there's any such special mechanism to locate the symbols, so you'll have to fall back to standard .NET methods. The first thing I'd try is to ensure your symbols for the custom resolver class are located in the same place as the assembly (i.e. your bin directory). Failing that you could perhaps configure a symbols path in Visual studio.
The first thing to do is to watch the debug output in Visual Studio. If you start the process and then attach to it, you will see the various assemblies being loaded. If Visual Studio can find the symbols, you will see that the output says "Symbols Loaded".

Where should connection strings be stored in a n-tier asp.net application

Folks,
I have an ASP.NET project which is pretty n-tier, by namespace, but I need to separate into three projects: Data Layer, Middle Tier and Front End.
I am doing this because...
A) It seems the right thing to do, and
B) I am having all sorts of problems running unit tests for ASP.NET hosted assemblies.
Anyway, my question is, where do you keep your config info?
Right now, for example, my middle tier classes (which uses Linq to SQL) automatically pull their connection string information from the web.config when instantiating a new data context.
If my data layer is in another project can/should it be using the web.config for configuration info?
If so, how will a unit test, (typically in a separate assembly) provide soch configuration info?
Thank you for your time!
We keep them in a global "Settings" file which happens to be XML. This file contains all the GLOBAL settings, one of which is a connection string pointing to the appropriate server as well as username and password. Then, when my applications consume it, they put the specific catalog (database) they need in the connection string.
We have a version of the file for each operating environment (prod, dev, staging, etc). Then, with two settings -- file path (with a token representing the environment) and the environment -- I can pick up the correct settings files.
This also has the nice benefit of a 30 second failover. Simple change the server name in the settings file and restart the applications (web) and you have failed over (of course you have to restore your data if necessary).
Then when the application starts, we write the correct connection string to the web.config file (if it is different). With this, we can change a website from DEV to PROD by changing one appSettings value.
As long as there isn't too much, it's convenient to have it in the web.config. Of course, your DAL should have absolutely no clue that it comes from there.
A good option is for your data layer to be given its config information when it is called upon to do something, and it will be called upon to do something when a web call comes in. Go ahead and put the information in your web.config. In my current project, I have a static dictionary of connection strings in my data layer, which I fill out like so in a routine called from my global.asax:
CAPPData.ConnectionStrings(DatabaseName.Foo) =
ConfigurationManager.ConnectionStrings("FooConnStr").ConnectionString()
CAPPData.ConnectionStrings(DatabaseName.Bar) =
ConfigurationManager.ConnectionStrings("BarConnStr").ConnectionString()
etc.
"Injecting" it like this can be good for automated testing purposes, depending on how/if you test your DAL. For me, it's just because I didn't want to make a separate configuration file.
For testing purposes don't instantiate DataContext with default ctor. Pass connection string info to constructor.
I prefer to use IoC frameworks to inject connection to data context then inject context to other classes.

Assembly unavailable after Web.config change

I'm using a custom framework that uses reflection to do a GetTypeByName(string fullName) on the fully-qualified type name that it gets from the database, to create an instance of said type and add it to the page, resulting in a standard modular kind of thing.
GetTypeByName is a utility function of mine that simply iterates through Thread.GetDomain().GetAssemblies(), then performs an assembly.GetType(fullName) to find the relevant type. Obviously this result gets cached for future reference and speed.
However, I'm experiencing some issues whereby if the web.config gets updated (and, in some scarier instances if the application pool gets recycled) then it will lose all knowledge of certain assemblies, resulting in the inability to render an instance of the module type. Debugging shows that the missing assembly literally does not exist in the current thread assemblies list.
To get around this I added a second check which is a bit dirty but recurses through the /bin/ directory's DLLs and checks that each one exists in the assemblies list. If it doesn't, it loads it using Assembly.Load and fixing the context issue thanks to 'Solving the Assembly Load Context Problem'.
This would work, only it seems that (and I'm aware this shouldn't be possible) some projects still have access to the missing assembly, for example my actual web project rather than the framework itself - and it then complains that duplicate references have been added!
Has anyone ever heard of anything like this, or have any ideas why an assembly would simply drop out of existence on a config change? Short of a solution, what is the most elegant workaround to get all the assemblies in the bin to reload? It needs to be all in one "hit" so that the site visitors don't see any difference other than a small delay, so an app_offline.htm file is out of the question. Programatically renaming a DLL in the bin and then naming it back does work, but requires "modify" permissions for the IIS user account, which is insane.
Thanks for any pointers the community can gather!
Generally, you should avoid relying on what assemblies are currently loaded in an appdomain, as that happens dynamically. Instead, simply call System.Web.Compilation.BuildManager.GetType() instead of Type.GetType() or Assembly.GetType(). This should just do the right thing for you, and not be affected by appdomain cycles.
As you obviously know, there are many situations where the current appdomain is unloaded and reloaded. After each reload, all assemblies are unloaded and the whole application starts running "from scratch".
Assemblies are by default loaded on demand. Usually that is the case when the JIT stumbles across some reference. In consequence, a appdomain reload will clear out the assemblies in the appdomain and they will only appear again later on when the JIT loads them.
As solution I'd rever to using the static Type.GetType() method and supply an assembly qualified name (e.g. a type name with the assembly name included). That's the same thing the framework uses when loading types specified in the config file, and it will make sure that the required assembly is searched and loaded on demand without using any tricks. See the remarks section of the method above (the method name above name is a link).
This will require updates to your database to hold assembly qualified names instead of "only" fully qualified type names. However, it also makes sure that you don't run into name collisions when two assemblies provide different type with the same name, so this is a good idea anyways I think.
I've never heard of this problem before.
I'm not sure if this will work, as I only recently read about it while researching workarounds to ODAC dependencies, but specifying the probing path for assemblies may fix your issue.
see: http://msdn.microsoft.com/en-us/library/823z9h8w(VS.80).aspx
sample:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="bin;bin2\subbin;bin3"/>
</assemblyBinding>
</runtime>
</configuration>
I have a similar problem, when I update 2-5 files, ether web.config, ether other files, and asp.net needs to recreate the running files, then some times did not find some classes/function that exist on dll files, and my system is not working - throw errors like yours.
My solution to that is that I place the app_offline.htm on the root, make my updates, then rename/remove the app_offline.htm and my system works fine.
I am sure that have something to do with the cached compiled files, but I did not have deaply search whats exactly cause that.
[what is the most elegant workaround to get all the assemblies in the bin to reload]
Now what is the most elegant workaround on this is to call the HttpRuntime.UnloadAppDomain and actually make your application to stop and starts again.
http://msdn.microsoft.com/en-us/library/system.web.httpruntime.unloadappdomain(VS.80).aspx
I do not know if this solve your issue, you need to make tests.
probably on Global.asax make something like that
void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError().GetBaseException();
...if ex is your error, and you get more than 2 ...
{
HttpRuntime.UnloadAppDomain();
}
}
I would try to create some basic class from which assembly, which is interesting for you without reflection on Application Start to make sure it is loaded.
E.g.
var temp = new BaseModuleBuilder();
This do not look smart, but it is very straitforward and asp.net should do everything for you. In case when your list is too dynamic, it could be something like
var temp = Activator.CreateInstance(Type.GetType("BaseModuleBuilder, Modules.dll"));
Make sure to always specify DLL when working with dynacmically loaded classes.

Resources