Background
I've taken over a very large asp.net website project. The old deploy process was to copy .cs, .aspx, and .ascx files to IIS and have it build on the fly. I want to precompile it and use TeamCity to automatically deploy it. I've done this with some of the other website projects.
The project has about 350 user controls that are nicely organized in folders but are used all over the place. Controls referenced from other folders, from each other... Basically a circular file reference nightmare.
My Attempt
My first attempt was to build it like the others. MSbuild the whole vs2012 solution. I ran into tons of "circular file references are not allowed". Come to find out all these nicely organized controls are used everywhere and there are circular references are all over the place. I read this and I switched the "web.config" to compilation batch="false" and then in the build set the site to "not be updateable" and "use fixed naming assemblies". The site builds but takes literally 25 minutes to compile on my quad core, ssd, 16gb ram dev box. This is unacceptable build times.
I know that if I turn off "use fixed naming assemblies" that the site would build significantly faster. (I've proven it on one of the smaller websites. It went from 4 minutes to 45 seconds). When I do remove that setting I'm getting weird build errors:
c:\Projects\Web\Site.master(146): error CS0433: The type 'ASP.usercontrols_modules_viewprofilepopup_ascx' exists in both 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\web\8d37b2c6\4c39f0a\App_Web_viewprofilepopup.ascx.4101713c.dll' and 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\web\8d37b2c6\4c39f0a\App_Web_xa514so5.dll'
c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\web\8d37b2c6\4c39f0a\App_Web_site.master.cdcab7d2.0.cs(927): error CS0433: The type 'ASP.usercontrols_modules_viewprofilepopup_ascx' exists in both 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\web\8d37b2c6\4c39f0a\App_Web_viewprofilepopup.ascx.4101713c.dll' and 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\web\8d37b2c6\4c39f0a\App_Web_xa514so5.dll'
error ASPPARSE: c:\Projects\web\Web\UserControls\Modules\JobsLeftMenu.ascx(128): error CS0433: The type 'ASP.usercontrols_modules_imagesgallerymodule_ascx' exists in both 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\web\8d37b2c6\4c39f0a\App_Web_imagesgallerymodule.ascx.4101713c.dll' and 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\web\8d37b2c6\4c39f0a\App_Web_nvrj33tx.dll'
error ASPPARSE: c:\Projects\web\Web\Site.master(146): error CS0433: The type 'ASP.usercontrols_modules_viewprofilepopup_ascx' exists in both 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\web\8d37b2c6\4c39f0a\App_Web_viewprofilepopup.ascx.4101713c.dll' and 'c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\web\8d37b2c6\4c39f0a\App_Web_xa514so5.dll'
Here is the exact aspnet_compiler.exe command:
aspnet_compiler.exe -v /web -p Web\ -f "Precompiled Web"
I googled around for answers. NO, they aren't duplicated in the code anywhere. They just happen to be in different folders, used by other controls in different folders. I have a feeling this is due to the circular file reference thing. Ok... Fine. I removed the usage of a few of these to see if it would build and the build process just moves onto other errors just like this one. I can't just remove code all over to accommodate this... How can I fix these errors without turning on "use fixed naming assembilies"?
Thing's I've Tried
Cleared the Temporary ASP.NET Files all throughout my system.
Tried a "publish" right from within visual studio 2012. Same errors.
Tried converting the site to a Web Application but got too many errors (upwards of 600+).
Again: made sure that there was no duplicate files and code that would explain it. I text searched the entire solution folder with notepad++ to validate that there wasn't another control with the same name.
Checked this.
I have msbuild performance tweaks turned on: /m /p:CreateHardLinksForCopyLocalIfPossible=true /p:BuildInParallel=true
I'm stumped and seem to think my only option is to rewrite the app, slog through the errors as I convert to a Web Application, or continue deploy source to the webserver but do it automated.
I known you've tried that already, but avoiding the circular references is going to be your best bet here. Note that the term 'circular reference' is actually not quite correct. What the build system complains about is circular references at the directory level, not the file level.
e.g. sub1\page.aspx uses sub2\uc1.ascx uses sub1\uc2.ascx
At the file level, there is no circle, but at the directory level there is, and that messed up with the way batching works.
While it may seem like you have so many of these situations as to make it unfixable, I'd bet that if you look at the details of the 'directory circles', it's down to not all that many. Drawing the reference graph might help make sense of things.
Then you just need to move the offenders into a different folder and change the links accordingly.
Yes, it's a painful process, but it is likely solvable.
Related
I am trying to convert a Windows Forms application to UWP using the Desktop Bridge. Since I have (most of) the source code, I'm attempting the conversion using Visual Studio, as opposed to the command-line tool. My application uses some third-party DLLs whose source code I don't have.
After adding a new JavaScript UWP project to my solution, I'm placing the original application's DLLs in a project subfolder as explained in the documentation.
Some of these DLLs are causing strange errors when I build the UWP project. The errors seem to be caused by duplicate resource entries in the DLLs, but curiously enough, these DLLs are referenced without issue in my standard Windows Forms project.
The errors state:
Duplicate entry
'DevExpress.Data.PropertyNamesRes/DevExpress/XtraPrinting/XpsDocumentOptions'
or one of its parents is defined as both resource and scope, which is
not allowed
I've been digging and searching about these errors for hours but I haven't found any meaningful information. I also used ILDASM to analyze the DLL headers but found no obvious issues in them. Has anyone here faced similar issues? Thanks in advance for any information.
Without seeing the complete error is difficult to say, but I've seen similar errors processing resources. If this is the case, this could be the same as this issue
And can be solved adding this property to the jsproj:
<AppxGeneratePrisForPortableLibrariesEnabled>false</AppxGeneratePrisForPortableLibrariesEnabled>
I'm trying to set up Jenkins with MSBuild plugin. I got Jenkins to check out solution from repository and run a build. But every build fails with several
error CS0433: The type 'CustomControls_WarningPopup' exists in both (...)
WarningPopup is an .ascx defined twice - once per web site project, and there are two website projects in the solution. The thing is this never rises any problems when compiling whole solution from VS2010. Should I run MSBuild with some specific parameters to make it behaving like VS?
I already tried moving Temporary ASP.NET files to custom folder (like in this answer) and it didn't help. Probably I'm missing something obvious to CI experts here...
I found the cause. There was another UserControl in second project which accidentally inherited class of the same name. Both controls were in the same directory and nor Visual Studio during compilation nor ReSharper saw anything wrong with this. Moreover MSBuild threw errors in both Web Projects despite the duplicated control was in only one of them. The funniest part is that this situation was like this for months and never rised any problems...
Anyway changing class of this control solved the issue and finally automated build succeeded!
Just read about the possibility to use codefile=somefile.aspx.cs instead of codebehind=somefile.aspx.cs in web application projects (described here). Obviously this causes the file the compile only when loading the page, it's not precompiled anymore (right?).
Are there any negative or unexpected side-effects by using codefile instead of codebehind in a web application project?
I think you could run into problems for supportability if your site isn't all one or the other. (CodeFile or CodeBehind)
i.e. If you're trying to figure out a problem on your production site that your error handling tells you is within a certain file or namespace, you'll have to stop to examine every file and control that you are supporting before troubleshooting to see if the page is running as part of the compiled assembly or running from the codebehind on the site.
You could also run into conflicting or missing namespaces if you try to have a mixed environment.
Pros as I see it for CodeFile:
Your production source code can sit on your production website. If the code is all compiled in a DLL in your bin directory, there is no absolute guarantee that the code you have on your development environment or source control is what's out there. (Sure it SHOULD be, but if everything was always as it should be, many of us wouldn't have jobs fixing other people's code!)
For updates, you only have to push out single files, not an entire assembly.
You would be able to have developments in progress on other pages that you don't need to back out before recompiling and publishing to production.
Cons:
Since you're not pushing out a compiled assembly, you may have errors within individual files, that won't necessarily be caught unless someone visits each specific page or if you are sure to compile before deploying.
You may have conflicting namespaces in codefiles that may never be caught and could cause confusion or errors.
Performance issues for dynamic compilation
I have some user controls in the project kept under a folder UserControls.
I'm using one of the user control from that folder in my master page and one on Default.aspx. The default.aspx uses that master file.
The problem is that everything was working fine until something happened and it seems user control is not getting compiled. The user control calls a method from Business Logic which was parameterless before (when everything was working fine) but when I changed it to accept parameters and of course its calls too, it started giving the error. It is still searching for that parameterless method..!! :(
I did tried manually deleting the DLLs, deleting the user controls and again creating them. But nothing worked.
Anyone has any idea what I did wrong or what am I missing??
Try checking the build configuration manager (Visual Studio 2008 -> Build -> Build Configuration Manager). I ran into a similar issue and it turned out that one of the projects I was referencing was not marked to actually build (there is a check box that should be checked to build the assembly). Try changing the assembly version number of the assembly that is creating the issue, rebuild, then check that the version number of that assembly is correct.
I came across this problem and it was due to the fact an older version of my bin-deployed assembly existed in the GAC. Unfortunately there is no way to force DLLs to load from the bin directory if the GAC version has the same version number. See here: Dll in both the bin and the gac, which one gets used?
After pre-compiled a ASP.NET web site, I got many files with the names like
App_Web_accountbalance.aspx.dfa151d5.dll
Do you know the rule for the random chars (in bold) above?
Can we fix the random chars?
The reason to fix it is that if we modify AccountBalance.aspx file later and re-compile the web site, can we just replace App_Web_accountbalance.aspx.dfa151d5.dll.
Thank you.
The characters are not random, but more in line with hashing. The purpose is to make the file name unique in the bin folder. Although not advisable, you can replace just certain files to update your website. If you modify AccountBalance.aspx and recompile, you need to replace App_Web_accountbalance.aspx.dfa151d5.dll, accountbalance.aspx.dfa151d5.compiled, and other assemblies and files that your aspx file depends.
I derived the answer from my experience. I was not looking for the file naming rule, but a way to deploy just the assembly of a changed page, same reason as the original post.
The setup:
A web application, deployed non-updateable (updatable=”false” in PrecompileApp.config), pre-compiled assemblies with no fixed names
What I did:
Make the change to the page (say, a.aspx) in development (Visual Studio 2010)
Publish the site with fixed naming to local drive (Build > Publish Web Site, check the box: Use fixed naming and single page assemblies)
Go to the bin folder of the local publish site and look for a.aspx.xxx.compiled
Open the file with Notepad and note any dependency (say, b.aspx, c.master)
Copy all the affected assemblies and the .compiled files to the bin folder in production server. In this example, they are:
a.aspx.xxx.compiled
b.aspx.xxx.compiled
c.master.xxx.compiled
App_Web_a.aspx.xxx.dll
App_Web_b.aspx.xxx.dll
App_Web_c.master.xxx.dll
If you want to know my story, the change was due to a change in a factor in a calculation. The customer knew of the change much earlier, but did not let us know until it became urgent. A proper deployment would involve other parties and much coordination, and would be too late. Plus, I only had the source code of two versions back, and requesting the latest would take time. So, a hot fix on just that calculation change was required as a temporary measure.
1) you can generate single assembly per web application if you want. So when you make a change in web application, you only need to deploy just one dll.
for this, you can check option "Use fixed naming and single page assemblies"
2) Reference from MSDN Article: "The assembly names are generated automatically by the compiler and it is therefore not obvious which assemblies map to which source files. The compiler also creates new names each time it runs, so that the names of assemblies might not be the same after each compilation. In addition, if source files have changed, the compiler might batch up source files differently, meaning that the resulting assemblies do not necessarily represent the same source files. If you are maintaining a deployed Web site and want to update only the assemblies for recent changes, the output from batch compilation can make that job more complicated.
To help you in this situation, aspnet_compiler.exe supports an option specifically designed for packaging and release management: the -fixednames option. This option enables you to create compiler output that has two benefits. The first is that the assemblies produced by the compiler have the same names each time you compile. The second is that the assemblies are based on the same input files each time."
http://msdn.microsoft.com/en-us/library/aa479044.aspx