System.Drawing namespace can't be used in Web Service - asp.net

I've put together a c# console app that runs a web service intending to download a simple pdf document. I can return the object however I can't seem to be able to figure out how to save the pdf object to file.
ServiceName.ImageResponse responseObject = Response.GetDocument(12345);
MemoryStream ms = new MemoryStream(responseObject.Document);
//System.Drawing is the problem (namespace can't be used in a Web Service)
System.Drawing.Image Img = System.Drawing.Image.FromStream(ms);
Img.Save("c:\\saved.JPG");
This is not compiling as I'm receiving (a red squiqly line under System.Drawing and) the following error:
Error 1 The type or namespace name 'Drawing' does not exist in the namespace 'System' (are you missing an assembly reference?)
http://msdn.microsoft.com/en-us/library/system.drawing.aspx states the following:
Caution noteCaution
Classes within the System.Drawing namespace are not supported for use within a Windows or ASP.NET service. Attempting to use these classes from within one of these application types may produce unexpected problems, such as diminished service performance and run-time exceptions. For a supported alternative, see Windows Imaging Components.
I would simply like to know if there is another way. I can't seem to figure it out.

trebuchet is probably correct. Check to make sure that you have actually done the work of adding a reference to the required dll. Namespaces do not have a 1 to 1 correspondence to .dll files, for what it is worth.
As to this:
Classes within the System.Drawing namespace are not supported for use
within a Windows or ASP.NET service. Attempting to use these classes
from within one of these application types may produce unexpected
problems, such as diminished service performance and run-time
exceptions. For a supported alternative, see Windows Imaging
Components.
I don't know for certain, but my guess is that several of the components within the System.Drawing namespace expect the process to have access to a window station, the desktop, etc., which is where you would see run-time exceptions. I'd take a punt and see if it works (once you've fixed your compilation error). What they're really saying here is "don't call us if this breaks" :)

Related

Qt and Linking to an external DLL

I've developed a program and I am trying to make this program work with a controllable light source manufactured by some other company. I've emailed the company and they have agreed to send me their external library as a DLL.
I have developed all of my software using Qt 4.8.1 and it has been compiled using MSVC2008.
The controllable light's DLL was compiled in Visual Studio 2008 and was written in either C++ or C# (the manufacturer is uncertain). All I have been given is the DLL and a text file saying that I must:
Add the DLL as a reference to my project
Add using LightName; to the top of the class
Instantiate an instance of the object like so: LightName *ln = new LightName();
Call function void turnOn() with the newly created LightName instance.
Firstly, I find it odd that an external library requires me to instantiate an instance of their object especially when its for a simple piece of hardware.
Secondly, the other company has provided me with no interface files.
My question is:
How can I possibly link to a C++ DLL and expose the functions nested in this library without having an interface header file in a Qt environment? Is there someway to make an interface for an external library?
I have already attempted using QLibrary and doing the following:
QLibrary myLib("mylib");
typedef void (*MyPrototype)();
MyPrototype myFunction = (MyPrototype) myLib.resolve("mysymbol");
if (myFunction)
myFunction();
However, this doesn't work because the DLL I was given was not a C DLL and I have no interface so Qt doesn't have a clue about what symbols it needs to resolve.
I've attempted to display all the definitions exported from my DLL using the dumpbin /EXPORTS command. Unfortunately this was unable to produce anything. I was hoping that I would get some sort of mangled C++ from this that I could then unscramble to make my own header.
I've attempted to use the dependency walker(very useful tool) however it couldn't resolve any symbols to give me some function definitions.
QLibrary only helps you if the library has functions exported as C symbols. If that is C++ you can dump the symbol table and look if that is sufficient for you. Names must be demangled: try to look for dumpbin or similar. It is however possible that you can't do this, it depends on how the symbols have been defined. In that case you'll have to ask for the header: read this.
Well it's absolutely legal to ask you for "instantiating an instance of their object". It's been simply their design decision to make the dll interface object oriented (as contrary to plain extern "C"). QtCore.dll is just someone else's DLL too, and you are instantiating their objects all the time.
But it also means that you will have harder time to call the DLL. The symbols are not "C" symbols (you can't export class that way) so QLibrary can't do anything for you. You can try dumpbin /EXPORTS from the DLL and then tediously unmangle them to reconstruct the class declaration. Luckily there are tools to help you (even online)
But not providing a header file for such DLL is completely dumb in the first place.

Accessing LinqBridge from JSON.NET dll

I am using JSON.NET which has the LinqBridge .dll merged in. LinqBridge allows Linq to be accessed from .NET 2. If I try to use Linq, even after importing System.Linq, I receive the following error:
Error 13 Could not find an implementation of the query pattern for source type 'int[]'. 'Where' not found. Are you missing a reference to 'System.Core.dll' or a using directive for 'System.Linq'? C:\Users\chrisl\Desktop\SoftTokens\Windows Desktop Soft-Token\Program.cs 27 25 WindowsSoftToken
If I try to include LinqBridge, then because JSON.NET already includes it, I receive this warning. Additionally, I have included the same component twice, which is inefficient:
Warning 2 The predefined type 'System.Action' is defined in multiple assemblies in the global alias; using definition from 'c:\Users\chrisl\Desktop\SoftTokens\Windows Desktop Soft-Token\libs\Newtonsoft.Json.Net20.dll' WindowsSoftToken
If I browse Newtonsoft.Json.Net20 in the object browser, I see that System.Linq appears empty, even after I have slected Show hidden types and methods.
Is it possible to access Linq from the JSON.NET dll or to suppress the error messages?
The Enumerable static class that provides the LINQ query operators in the LINQBridge assembly is still exposed in the System.Linq namespace.
You still need to have the using directive for System.Linq as directed in your first error message.
Update:
It turns out the LINQBridge assembly that's merged into Newtonsoft.Json.Net20.dll has been "internalized" which I hadn't noticed at first. This means your code can't reference the Enumerable type that the compiler needs to "implement the query pattern." So you do have to reference the LINQBridge assembly yourself, but then you get the warning about duplicate definitions as you mentioned.
You can disable the duplicate class warning by going to the Build tab of your project properties and enter "1685" in the "Suppress warnings:" box.
But what would probably be better would be to build your own version of JSON.net from source without merging in LINQBridge.

WCF: Should all datacontracts use the same namespace?

I have several service contracts exposed over WCF, which use multiple datacontracts. The service is to be consumed by Adobe Flex. I've run into many problems getting Flex to consume the WSDL produced by the server. I used the procedure outlined here to squeeze the WSDL into a single file (I used FlatWsdl and not WcfExtras, if it matters).
Now I'm getting a bunch of errors when using VS2010's own wsdl.exe tool to extract my metadata. Specifically, I'm getting the following errors:
1) Schema validation warning: Schema item 'complexType' named
'ArrayOfKeyValueOfSomeKeySomeValuep1alXzIb' from namespace
'http://schemas.microsoft.com/2003/10/Serialization/Arrays' is invalid.
Namespace 'http://My/Wcf/Namespace' is not available to be referenced
in this schema.
2) Schema validation warning: Schema item 'complexType' named 'MyComplexType'
from namespace 'http://My/Wcf/Namespace' is invalid. Namespace
'http://schemas.datacontract.org/2004/07/My.Real.Namespace' is not available
to be referenced in this schema.
Now, the Dictionary ("ArrayOfKeyValueOf...") type is apparently defined in an external schema, which is not imported by my WSDL. Please note that SomeKey and SomeValue have a datacontract namespace of My/Wcf/Namespace.
As for MyComplexType, the weird thing is that if I change its Datacontract-namespace to the same namespace used by my services, servers, and bindings, then error (2) goes away. I can't figure out why.
What I'm asking boils down to two questions:
1) How can I add an import directive of an external schema to my WSDL? I saw some solutions on-line that suggested writing a wrapper class around the containers. This is something I would really like to avoid.
2) Do I really have to put all my datacontracts into a single namespace? I don't have any technical objection to doing it, but it's going to be very cumbersome to modify the namespace of all datacontracts. Perhaps there's an automated way of achieving this?
TIA!
So just in case anyone else runs into the same problem with accessing a WCF (BasicHttpBinding) server from a Flex client:
1) No, all DataContracts need not be in the same namespace (but all ServiceContracts, service implementations, and bindings do have to be in the same namespace!).
2) The crux of the problem is that Flex expects each xsd:schema to have an "xsd:import namespace" for all the namespaces it references. This import should be of the form:
<xsd:import namespace="http://schemas.datacontract.org/2004/07/SomeNamespace" />
There doesn't seem to be a way to do this with WCF, since it automatically adds an auto-generated schemaLocation attribute to this tag, which makes Flex try to fetch this schemaLocation. The only workaround appears to be manually manipulating the WSDL at the XML level (e.g. by exposing a REST endpoint for retrieving the metadata).
Thanks to Yaron Naveh in the MSDN WCF forums for his help. The discussion can be found at http://social.msdn.microsoft.com/Forums/en/wcf/thread/b9429e30-e4d5-454f-9fbd-bae39990ff33.

ASP.NET page or control marked as internal doesn't work and gives "inaccessible due to its protection level" error

I know why this happens and I want to find a workaround it.
Example: a user control that exist in 2 assemblies, loaded at the same time.
namespace MyNamespace
{
internal class MyUserControl : UserControl
{
}
}
My situation - I want to be able to share user interface control between two web applications which are loaded at the same time in the same application pool. If my user interface class is marked public, then ASP.NET will not like it because it will be duplicated into memory ( CLR uses namespaces as full qualifier for class, and if the same class and namespace is met it more than one assembly, exception is thrown ). I do then mark the class as internal and of course I forget how UI compilation occurs, and I expect it to work. Of course it doesn't because ASP.NET compiles the UI into separate assembly which is dynamic and since I marked the class as internal, it is not visible to the main assembly...
The question that follows is: How can I make dynamic compiled assemblies that ASP.NET generates to view the main application assembly internals? It is very unfortunate that classes and methods I write into my UI controls must always be public! Has anyone met this obstacle in his daily work and found a workaround?
EDIT:
Precompilation is not possible here due to other circumstances.
You can share User Control markup between apps using a Virtual Path Provider (see
http://weblogs.asp.net/scottgu/archive/2005/11/27/431650.aspx and http://msdn.microsoft.com/en-us/library/system.web.hosting.virtualpathprovider.aspx).
You can pull the markup for the control from anywhere - SharePoint uses VPP to get markup from the database, and I use it in some projects to pull from a non-standard location on disk (which is shared between projects).
If your base class is internal, the derived class that ASP.NET generates at runtime will not be able to extend it.
However, I don't understand the issue that you're running into in the first place. Two distinct web applications will always run in different AppDomains (even if they're in the same app pool), and there should be no type conflicts between the AppDomains.
I probably need more details about what you are doing. e.g. what assembly are you compiling your base class into, and why does it end up in two different assemblies?

Problem reflecting in ASP.net context

I have a ASP.net application that is referencing a external assembly that I need to dynamically load and discover any types implementing a known interface. The problem I am having is that the type I reflect does not match the same interface that is running and so I cannot cast it.
Example:
This code is run in ASP.net app.
var assembly = Assembly.LoadFile(Path.Combine(HttpRuntime.BinDirectory, "ExternalAssembly.dll"));
var type = assembly.GetExportedTypes().First<Type>(x => x.Name == "AClass"); // AClass implements IAInterface
var reflectedInterface = type.GetInterface(typeof(IAmAInterface).ToString());
if (reflectedInterface != typeof(IAmAInterface))
throw new Exception("This makes me sad"); // This code gets run
The only difference I can see between the reflected interface I loaded from the bin and the interface returned from typeof is that the typeof assembly has a location in the temp ASP.net path (C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\08c43c8b\3adac8cf\assembly\dl3\eb7a4127\0235ea60_a3c8c901\ReflectionTest.DLL)
Thanks Paul Alexander I have changed the code to use the Assembly.Load method not Assembly.LoadFile which solves the problem.
wwilden: I also tried extracting the interface into it's own assembly and this does also solve the problem.
When you use LoadFile the assembly is not loaded into the same context as your other assemblies at runtime so to the CLR interface runtime types are different. You can read more in Suzanne Cook's Debugging Assembly Load Failures.
If the assembly that you're loading is already in the Bin directory - you can load it by name. You don't need to know the exact path as the Bin folder is already in the assembly probing path.
Where is your interface type defined? Does it exist both in the reflected assembly as well as in the application itself? Then you actually have two different interfaces, even though they have the same namespace and name.
What you need to do is extract the interface from the reflected assembly and put it into another assembly that you refer to both from the reflected assembly as well as your application. Then it should work.
Apart from your problem, if you have a lot of assemblies to dynamically load, remember that they will remain in memory until the ASP.NET worker process reloads. This could influence your server's performance.
You could load the assemblies in a separate AppDomain (the smallest unit that is possible to unload), load a proxy class in that AppDomain which you reference with .NET remoting. Once finished, you unload the AppDomain.
There is an interesting article over at CodeProject about a situation like this. Where you have a class that has a structure that is identical with an interface without implementing the interface itself. The article outlines a method of dynamically creating wrapper classes that implement the needed interface. It could be helpful in your situation.

Resources