ASP.NET MVC + Mono + Linux

Discussion of open issues, suggestions and bugs regarding ADO.NET provider for MySQL
tobiasly
Posts: 12
Joined: Tue 09 Mar 2010 16:18

ASP.NET MVC + Mono + Linux

Post by tobiasly » Wed 15 Dec 2010 05:29

This licensing issue has me so confused and I'd really like to solve it because otherwise it seems like yours is a great solution.

I want to deploy an ASP.NET MVC application on Linux (Ubuntu and/or CentOS) using Mono 2.6.7. The application itself will not contain the DotConnect LINQ code; this will be in a separate assembly. Let's call the app MyMvcApp and the dll MyMvcApp.Data.dll

So:

1. Do I need to embed the license code in just MyMvcApp.Data.dll, in just the ASP.NET MVC app, or both somehow?
2. If the app, how exactly do I do this? I do have access to Visual Studio to perform the compilation.
3. Do I need to compile the license file every time the DLL and/or MVC app changes, or can I compile it once on Windows then add it as a resource each time I compile on Linux? I'd prefer to *not* need Visual Studio for my regular development.

PLEASE, please don't just say that it's explained in detail in http://www.devart.com/dotconnect/mysql/ ... ml#compile because that doesn't reference ASP.NET MVC anywhere and it isn't at all clear whether I can compile the license once on Windows or have to compile it each time the code changes. I guess "Class Libraries Support" explains it a bit but an ASP.NET MVC site doesn't create an .exe so I don't know what to put in licenses.config.

And can I just say that all of this is extremely confusing and frustrating, yes I know it's "the standard Microsoft .NET licensing tool" but you have a great solution to a cross-platform problem here and I'd really LOVE to give you my money but this awkward manual process is just terrible. Please come up with a fully-managed way to control your licenses so that Mono/Linux users don't have to deal with this!! I really hope you're not going to say I have to compile in VS every time because that will probably cause me to look elsewhere :(

tobiasly
Posts: 12
Joined: Tue 09 Mar 2010 16:18

Post by tobiasly » Wed 15 Dec 2010 05:33

4. Also please explain how, if at all, the default namespace comes into play here. My ASP.NET MVC app has namespace "MyMvcApp" and the class library has namespace "MyMvcApp.Data.dll".

5. Is any of this case sensitive on Mono/Linux? I see that lc.exe creates files in all-lowercase which I'm guessing may not get picked up.

No matter what I've tried I keep getting RegistryKey errors. Thanks for your time...

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Thu 16 Dec 2010 17:52

Concerning your questions:

1) You can add the technical license to either of these projects; our license validator checks that the license resource is present in at least one assembly of the chain. Apparently, it is preferable to add the license to the DAL assembly.

2) To add license to your project (either the DAL one or the web application), you can compile the license resource with the lc.exe tool (on the machine where dotConnect for MySQL is installed), add it to the project and set its Build Action to 'Embedded Resource'.

3) Generally, you need to compile the license resource only once. However, you will need to recompile it if you update the version of dotConnect for MySQL you are using for this web application.

As ASP.NET MVC applications are compiled to a single assembly, you do not need to specify .exe files in licenses.config.

4) The assembly name for which you are compiling license should be specified in the lc.exe arguments, e.g.,

Code: Select all

"[Path_to_lc.exe]\lc.exe" /target:MyMvcApp.Data.dll /complist:licenses.licx /i:"[Path_to_the_assembly]\Devart.Data.MySql.dll"
5) Provided that the license resource is valid, its case should not matter. Please tell us if you have any additional questions or encounter any problems with this.

tobiasly
Posts: 12
Joined: Tue 09 Mar 2010 16:18

Post by tobiasly » Thu 16 Dec 2010 18:26

Thanks for your reply. I did compile the .licx file manually and then add it to the DAL. It seemed to run fine on Windows, but when I moved it to Mono/Linux got the following error. It is still trying to access the (non-existent) registry which I assume is a licensing error. Or am I way off base here?

One further question: do I need to add licenses to both Devart.Data.MySql.dll and Devart.Data.MySql.Linq.dll or just to one of them?

Really hope to get this resolved today, so I can spend time trying out your product and not messing with the license! We have multiple websites we would like to implement on Mono using your tool as long as we can verify it will adequately suit our needs. Our entire infrastructure is Linux and we really can't take on the expense of adding Windows servers to the mix...

Code: Select all

Server Error in '/' Application
No access to the given key

Description: HTTP 500. Error processing request.
Stack Trace: 
System.Security.SecurityException: No access to the given key
at Microsoft.Win32.KeyHandler..ctor (Microsoft.Win32.RegistryKey,string) 
at Microsoft.Win32.KeyHandler.Lookup (Microsoft.Win32.RegistryKey,bool) 
at Microsoft.Win32.UnixRegistryApi.OpenSubKey (Microsoft.Win32.RegistryKey,string,bool) 
at Microsoft.Win32.RegistryKey.OpenSubKey (string,bool) 
at Microsoft.Win32.RegistryKey.OpenSubKey (string) 
at (wrapper remoting-invoke-with-check) Microsoft.Win32.RegistryKey.OpenSubKey (string) 
at Devart.Common.c.a (string&,string&) 
at Devart.Common.b.a (System.ComponentModel.LicenseContext,System.Type,string&,bool&,string&,string&)
    
at Devart.Common.b.a (System.ComponentModel.LicenseContext,System.Type,bool) 
at Devart.Common.b.a (System.ComponentModel.LicenseContext,System.Type,object,bool) 
at Devart.Data.MySql.Linq.Provider.MySqlDataProvider.Initialize (object) 
at Devart.Data.Linq.Provider.DataProvider.Devart.Data.Linq.Provider.IProvider.Initialize
    (Devart.Data.Linq.IDataServices,object) 
at Devart.Data.Linq.DataContext.a (object,System.Data.Linq.Mapping.MappingSource,System.Type)
    
at Devart.Data.Linq.DataContext..ctor (string,System.Data.Linq.Mapping.MappingSource)
    
at MyAspSite.Data.Models.TabDataContext..ctor () 
at MyAspSite.Data.Repositories.BracketRepository.GetBracket (int) [0x0000d] in
    ~/work/site/MyAspSite.Data/Repositories/BracketRepository.cs:12
at MyAspSite.Controllers.HomeController.Index () [0x00006] in
    ~/work/site/MyAspSite/Controllers/HomeController.cs:22
at (wrapper dynamic-method) System.Runtime.CompilerServices.ExecutionScope.lambda_method
    (System.Runtime.CompilerServices.ExecutionScope,System.Web.Mvc.ControllerBase,object[])
    
at System.Web.Mvc.ActionMethodDispatcher.Execute (System.Web.Mvc.ControllerBase,object[])
    
at System.Web.Mvc.ReflectedActionDescriptor.Execute (System.Web.Mvc.ControllerContext,
    System.Collections.Generic.IDictionary`2) 
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod (System.Web.Mvc.ControllerContext,
    System.Web.Mvc.ActionDescriptor,System.Collections.Generic.IDictionary`2)
    
at System.Web.Mvc.ControllerActionInvoker/c__AnonStoreyB.m__E
    () 
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter (System.Web.Mvc.IActionFilter,
    System.Web.Mvc.ActionExecutingContext,System.Func`1)
    

tobiasly
Posts: 12
Joined: Tue 09 Mar 2010 16:18

Post by tobiasly » Fri 17 Dec 2010 00:48

OK, this is working now! Not sure what exactly I did differently, but it's working on Linux now when I:
  1. generate the .licenses file on Windows,
  2. embed the .licenses file into the ASP.NET MVC project manually in Visual Studio (set to embedded resource),
  3. compile in Visual Studio,
  4. copy compiled project to Linux,
  5. run with Mono (xsp2).
Next up I'll try compiling using MonoDevelop with the embedded .licenses resource. I'll also try to figure out what I did differently & post the results for others...

Update: ...and it's broken again. I'm doing the exact same steps as outlined above and it's not working on Linux anymore. Maybe it was automatically embedding previously and I broke it trying to compile/embed manually. This is beyond frustrating. I've spent three days on this nonsense.

tobiasly
Posts: 12
Joined: Tue 09 Mar 2010 16:18

Post by tobiasly » Fri 17 Dec 2010 06:29

OK after MUCH trial and error I've finally been able to determine the actions which reliably allow me to compile and run my app under Mono (using MonoDevelop but I'm sure command line would work also) after initially creating the .licenses file on Windows.

So for posterity sake here is some detailed info.

Assumptions / notes:
  • I am creating an ASP.NET MVC app, which gets compiled into a single DLL (MyMvcApp.Web.dll);
  • I have a second assembly, MyMvcApp.Data.dll, which contains the data access logic.
  • MyMvcApp.Data.dll contains references to both Devart.MySql.dll and Devart.MySql.Linq.dll (it also contains references to Devart.Data.dll and Devart.Data.Linq.dll but these seem to be "common" DLLs which are not licensed).
  • MyMvcApp.Web.dll does NOT contain any references to any Devart DLLs, but contains a project reference to MyMvcApp.Data.dll.
So Step 1 is to create the .licenses file. Like many Microsoft products (sorry) Lc.exe will give terrible error messages or silently do the wrong thing with no indication it didn't work right. Here is the correct command line for my scenario above. NOTE: this must be run on the machine on which DotConnect is installed.

Code: Select all

lc.exe /target:MyMvcApp.Web.dll /complist:licenses.licx /i:[Path_to_assembly]\Devart.Data.MySql.dll /i:[Path_to_assembly]\Devart.Data.MySql.Linq.dll /v
So because none of the examples on this site or Microsoft's site actually explain what all of this means, here's the breakdown:

/target: This is the name of the DLL or EXE that will "host" the application, NOT NECESSARILY the DLL that has the references to the licensed components. Thus StanislavK's example above is NOT correct because it specifies /target as the Data.dll. For the MVC app this should be the MyMvcApp.Web.dll instead. Also note that, unlike /i, this is NOT A PATH! It's just the name of the DLL that will contain the running the app.

/complist: The licenses.licx file. This is a plain text file of the licensed components which need to be used. And since no example on this entire site got this one right, here's what it must contain:

Code: Select all

Devart.Data.MySql.Linq.Provider.MySqlDataProvider, Devart.Data.MySql.Linq
Devart.Data.MySql.MySqlConnection, Devart.Data.MySql
Because these are both licensed components, they both need to be in there, one per line (each line contains the name of a class that is licensed, and the name of the assembly which that class is in, without the .dll). Trust me on this one (unless for some reason you're only using one of them; I assume Devart.Data.MySql is always required and Devart.Data.MySql.Linq is if you use LINQ to MySql)

/i: Again, because there are two licensed components, you need two /i parameters, one for each. These must be actual paths to the DLLs being used (can be relative to the current directory) so that Lc.exe can actually load them up and call the licensing routines.

/v: To specify Verbose mode. This will let you see that the Lc.exe tool actually picks up both licensed components and includes them.

OK so after all this you have a .licenses file. THIS is the file that needs to be embedded as a resource in the root of the Web project. I just copied the file over to the root of my MVC project, right-clicked on the project in MonoDevelop, clicked "Add" then "Add Files", and added the .licenses file.

Then right-click on the added file in the project, choose Properties, and then change Build Action to "Embed as resource".

Now here's the part I'm not sure of... I swear that one time it didn't work correctly if I didn't fix the Resource ID on the Properties tab also. You'll see that it probably "doubled up" the namespace, like "MyMvcApp.Web.mymvcapp.web.dll.licenses" (yeah the Lc.exe tool creates the file in all lowercase but that shouldn't matter). Anyway I changed that Resource ID to the correct full name (just "MyMvcApp.Web.dll.licenses"), but now I'm not sure whether that actually matters.

Note that, in my case, it was NOT necessary to do ANYTHING to the MyMvcApp.Data.dll project! Even though it has the references to the components, it's not the assembly that runs. So in that sense it's much like the precompiled ASP.NET examples on the Licensing page, although that page gets the examples all wrong and yes those details matter (for example you don't need to embed the .licx file, just the .licenses file).

Anyway, if all of this works out you should be able to simply Debug or Run your application in MonoDevelop (or using xsp2 or mod_mono) and have it work without those annoying KeyHandler errors!

Hopefully this info saves the next person from having to endure three days of trial and error using bad and/or incomplete command line examples; I'm sure all of this is obvious to someone who works with these tools all the time but for those of us who never deal with component licensing each day it's not very easy at all!

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Mon 20 Dec 2010 15:56

Thank you for posting, and glad to see that the problem was resolved. Feel free to contact us if you encounter any other problems or have any additional questions on dotConnect for MySQL.

JIC:
a) The attempts to access the registry may occur when the license information was not found: in this case our license validator checks whether dotConnect for MySQL is installed in the system, and tries to read this information from the registry.

b) The license check is performed when opening a connection, thus only the MySqlConnection component (and thus the Devart.Data.MySql.dll assembly) actually needs to be specified in the licenses.licx file.

c) Any .dll or .exe file in the chain (i.e., either the web application assembly or the DAL assembly) may be used in the /target argument of lc.exe. The important thing is that the generated resource should be included into the project for which the .licenses file was compiled; i.e., if /target was MyMvcApp.Data.dll, then the resource should be added to the DAL.

tobiasly
Posts: 12
Joined: Tue 09 Mar 2010 16:18

Post by tobiasly » Mon 20 Dec 2010 16:10

StanislavK wrote:Thank you for posting, and glad to see that the problem was resolved. Feel free to contact us if you encounter any other problems or have any additional questions on dotConnect for MySQL.
Thanks for the follow-up. A couple points:
  • The licensing helper tool in VS was not very useful throughout all of this. It didn't seem to recognize that I had an MVC app and a DAL and that the former used the latter. It still wanted me to type DLL or EXE names into a listbox which never seemed to help.
  • If you had any viable competition I would have given up long ago :-) I'm glad I got it working but it was way too much work and the docs/examples never seemed to work right.
StanislavK wrote:b) The license check is performed when opening a connection, thus only the MySqlConnection component (and thus the Devart.Data.MySql.dll assembly) actually needs to be specified in the licenses.licx file.
Thanks for the info, I'm pretty sure I ran into problems when I only included Devart.Data.MySql.dl but I'll try again without it and update if it works.
StanislavK wrote:c) Any .dll or .exe file in the chain (i.e., either the web application assembly or the DAL assembly) may be used in the /target argument of lc.exe. The important thing is that the generated resource should be included into the project for which the .licenses file was compiled; i.e., if /target was MyMvcApp.Data.dll, then the resource should be added to the DAL.
Good to know, again it's something that was probably obvious to you but not to someone like me who has never dealt with component licensing!

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Tue 21 Dec 2010 10:18

The License wizard is designed to create files (licenses.licx and licenses.config) with which Visual Studio can compile the license resource. These files cannot be used under Mono, as dotConnect for MySQL cannot be installed under this OS.

We will analyze the possibility of creating the license resource itself via the License wizard. We will inform you about the results of our investigation.

tobiasly
Posts: 12
Joined: Tue 09 Mar 2010 16:18

Post by tobiasly » Tue 21 Dec 2010 15:00

StanislavK wrote:The License wizard is designed to create files (licenses.licx and licenses.config) with which Visual Studio can compile the license resource. These files cannot be used under Mono, as dotConnect for MySQL cannot be installed under this OS.

We will analyze the possibility of creating the license resource itself via the License wizard. We will inform you about the results of our investigation.
That would definitely make the whole process much easier, thanks!

tobiasly
Posts: 12
Joined: Tue 09 Mar 2010 16:18

Post by tobiasly » Wed 22 Dec 2010 03:24

StanislavK wrote: b) The license check is performed when opening a connection, thus only the MySqlConnection component (and thus the Devart.Data.MySql.dll assembly) actually needs to be specified in the licenses.licx file.
I can confirm that this is incorrect. When I remove Devart.Data.MySql.Linq.dll from the above procedures, I get the following error. You can see that the last call prior to the LicenseContext invocation is to Devart.Data.MySql.Linq.Provider.MySqlDataProvider.Initialize. Thus it is necessary to include licenses for *both* DLLs.

Code: Select all

System.Security.SecurityException: No access to the given key
at Microsoft.Win32.KeyHandler..ctor (Microsoft.Win32.RegistryKey,string) 
at Microsoft.Win32.KeyHandler.Lookup (Microsoft.Win32.RegistryKey,bool) 
at Microsoft.Win32.UnixRegistryApi.OpenSubKey (Microsoft.Win32.RegistryKey,string,bool) 
at Microsoft.Win32.RegistryKey.OpenSubKey (string,bool) 
at Microsoft.Win32.RegistryKey.OpenSubKey (string) 
at (wrapper remoting-invoke-with-check) Microsoft.Win32.RegistryKey.OpenSubKey (string) 
at Devart.Common.c.a (string&,string&) 
at Devart.Common.b.a (System.ComponentModel.LicenseContext,System.Type,string&,bool&,string&,string&) 
at Devart.Common.b.a (System.ComponentModel.LicenseContext,System.Type,bool) 
at Devart.Common.b.a (System.ComponentModel.LicenseContext,System.Type,object,bool) 
at Devart.Data.MySql.Linq.Provider.MySqlDataProvider.Initialize (object) 
at Devart.Data.Linq.Provider.DataProvider.Devart.Data.Linq.Provider.IProvider.Initialize (Devart.Data.Linq.IDataServices,object) 
at Devart.Data.Linq.DataContext.a (object,System.Data.Linq.Mapping.MappingSource,System.Type) 
at Devart.Data.Linq.DataContext..ctor (string,System.Data.Linq.Mapping.MappingSource) 
at MyMvcApp.Data.Models.TabDataContext..ctor () 
at MyMvcApp.Data.Repositories.BracketRepository..ctor () 
at MyMvcApp.Controllers.HomeController.Index () 
at (wrapper dynamic-method) System.Runtime.CompilerServices.ExecutionScope.lambda_method (System.Runtime.CompilerServices.ExecutionScope,System.Web.Mvc.ControllerBase,object[]) 
at System.Web.Mvc.ActionMethodDispatcher.Execute (System.Web.Mvc.ControllerBase,object[]) 
at System.Web.Mvc.ReflectedActionDescriptor.Execute (System.Web.Mvc.ControllerContext,System.Collections.Generic.IDictionary`2) 
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod
  (System.Web.Mvc.ControllerContext,System.Web.Mvc.ActionDescriptor,
  System.Collections.Generic.IDictionary`2) 
at System.Web.Mvc.ControllerActionInvoker/c__AnonStoreyB.m__E () 
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter
  (System.Web.Mvc.IActionFilter,System.Web.Mvc.ActionExecutingContext,
  System.Func`1) 

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Wed 22 Dec 2010 16:01

I will send you a sample solution in a letter, please check that it was not blocked by your mail filter.

Please perform the following steps:

1) On the machine where dotConnect for MySQL is installed, please compile the license resource for the TestClassLibrary\licenses.licx file; the command should be

Code: Select all

"[Path to lc.exe]\lc.exe" /target:TestClassLibrary.dll /complist:"[Path to licenses.licx]\licenses.licx" /i:"[Path to the assembly]\Devart.Data.MySql.dll"
Replace the TestClassLibrary\testclasslibrary.dll.licenses file with the generated resource.

2) Place the following assemblies to the Bin folders of both TestClassLibrary and LinqLicenseTestInMVC projects:
Devart.Data.dll
Devart.Data.MySql.dll
Devart.Data.Linq.dll
Devart.Data.MySql.Linq.dll

3) Change the connection string used in the TestClassLibrary project.

4) Recompile and run the solution under Mono.

Please tell us if this works in your environment.

tobiasly
Posts: 12
Joined: Tue 09 Mar 2010 16:18

Post by tobiasly » Mon 03 Jan 2011 03:43

Sorry for the delay in response; I haven't been able to work on this with the recent holidays. I get mostly the same error when following the requested steps; following is the stack trace:

Code: Select all

System.Security.SecurityException: No access to the given key
at Microsoft.Win32.KeyHandler..ctor (Microsoft.Win32.RegistryKey,string) 
at Microsoft.Win32.KeyHandler.Lookup (Microsoft.Win32.RegistryKey,bool) 
at Microsoft.Win32.UnixRegistryApi.OpenSubKey (Microsoft.Win32.RegistryKey,string,bool) 
at Microsoft.Win32.RegistryKey.OpenSubKey (string,bool) 
at Microsoft.Win32.RegistryKey.OpenSubKey (string) 
at (wrapper remoting-invoke-with-check) Microsoft.Win32.RegistryKey.OpenSubKey (string) 
at Devart.Common.c.a (string&,string&) 
at Devart.Common.b.a (System.ComponentModel.LicenseContext,
  System.Type,string&,bool&,string&,string&) 
at Devart.Common.b.a (System.ComponentModel.LicenseContext,System.Type,bool) 
at Devart.Common.b.a (System.ComponentModel.LicenseContext,System.Type,object,bool) 
at Devart.Data.MySql.Linq.Provider.MySqlDataProvider.Initialize (object) 
at Devart.Data.Linq.Provider.DataProvider.Devart.Data.Linq.Provider.IProvider.Initialize (Devart.Data.Linq.IDataServices,object) 
at Devart.Data.Linq.DataContext.a (object,System.Data.Linq.Mapping.MappingSource,System.Type) 
at Devart.Data.Linq.DataContext..ctor (string,System.Data.Linq.Mapping.MappingSource) 
at TestContext.TestDataContext..ctor (string) 
at TestClassLibrary.Class1.GetDeptNames () 
at LinqLicenseTestInMVC.Controllers.HomeController.Index () 
at (wrapper dynamic-method) System.Runtime.CompilerServices.ExecutionScope.lambda_method (System.Runtime.CompilerServices.ExecutionScope,System.Web.Mvc.ControllerBase,object[]) 
at System.Web.Mvc.ActionMethodDispatcher.Execute (System.Web.Mvc.ControllerBase,object[]) 
at System.Web.Mvc.ReflectedActionDescriptor.Execute (System.Web.Mvc.ControllerContext,System.Collections.Generic.IDictionary`2) 
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod (System.Web.Mvc.ControllerContext,System.Web.Mvc.ActionDescriptor,
  System.Collections.Generic.IDictionary`2) 
at System.Web.Mvc.ControllerActionInvoker/c__DisplayClassd.b__a () 
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter (System.Web.Mvc.IActionFilter,System.Web.Mvc.ActionExecutingContext,
  System.Func`1) 

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Mon 03 Jan 2011 15:07

Could you please send us the generated license resource so that we are able to analyze the issue in details? In our environment, the test project is successfully compiled and run under Mono 2.6.7.

tobiasly
Posts: 12
Joined: Tue 09 Mar 2010 16:18

Post by tobiasly » Mon 03 Jan 2011 20:29

OK, I have just sent the file via your contact form.

Post Reply