Tag Archives: ASP.NET

Uncategorized

ASP.NET CS0016 – Compiler Access Denied

Once in a while, a developer will have one of those unbelievably frustrating problems with his environment or platform that makes him bang his head against the wall for hours.  I’m sure people in other trades have similar experiences somehow, but I don’t know of a good parallel offhand.

I just experienced such a problem with ASP.NET.  I just imported a deployment package of a self-hosted NuGet feed, which is just an empty ASP.NET application built as explained in the NuGet documentation.  Anyway, after importing the deployment package using webdeploy (via the IIS Management Console), I had an application under my default web site called “nuget”.  After that, I kind of expected it to Just Work, at least from the server itself.

 I opened Internet Explorer and navigated to http://localhost/nuget, and got the following nastiness:

Compiler Error Message: CS0016: Could not write to output file ‘c:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\62d43c41\27d749ca\App_Code.7lodcznm.dll’

The particular DLL the compiler was trying to write was different than shown, but this is the error.  Well, I found several posts just glibly saying “all you have to do is make sure the ‘Temporary ASP.NET Files’ permissions are set properly”.  It sure sounded easy enough.  Turns out, it was too easy, because it didn’t work.  I ended up giving full control to “Everyone” to kind of prove what was really going on.  After that didn’t work, I ran procmon and filtered carefully to find a non-SUCCESS event on a path including “temp” and by a process called “csc.exe” (the C# compiler).  Sure enough, I found this:

3:01:01.3158251 AM	csc.exe	6428	CreateFile	C:\Windows\Temp\RES3277.tmp	ACCESS DENIED
Desired Access: Generic Read, Disposition: Create, Options: Synchronous IO Non-Alert, Non-Directory File,
Attributes: N, ShareMode: None, AllocationSize: 0

You can see here that the actual error is not what appeared in the browser window, frustratingly. I gave Full Control permissions to the Everyone group on \Windows\Temp, and that seemed to fix it.

Well, that won’t do – it’s not a good idea to do the equivalent of “chmod 777″ on \Windows\Temp, so I needed to give access to just the DefaultAppPool user.  Well, guess what?  When I went through Explorer, I was not able to find the user through the UI to give it permissions.  Ultimately, I figured out that I could do it using icacls:

PS C:\Windows> icacls Temp /t /grant "IIS AppPool\DefaultAppPool:(F)"

After doing the same to the “Temporary ASP.NET Files”  folder, I was done.  Finally.  Now I’ve got a 404 error to fix…

Uncategorized

Lambdas in data-binding expressions

For a recent project, I wrote a templated web part (similar to the Smart Part) to do a search on a custom list and display the results (all using AJAX updates made available by the UpdatePanel), and I found myself unable to accomplish what I needed to accomplish in data-binding expressions inline in the user control loaded by my web part. I needed to be able to do multiple steps to condition the bound data before rendering it (for example, splitting a single field into multiple distinct fields that should be rendered differently).

For example, one of the bound fields I needed to render was a string formatted like this:

"http://www.website.com/page.aspx, Name of the Website"

I needed to render this as a link. Obviously, it won’t directly render properly. It needed to be split, so it could be rendered something like this:

Name of the Website

For this simple example, you can do it all inline without lambdas by taking advantage of the ability to pass an array as a params parameter:

String.Format("{1}",
             1

However, for a more complex case in which the bound data needs conditioning that can’t be done inline, typically you would do your conditioning and rendering in server side code2.

The problem with that is that you then have to write a bunch of methods that kind of pollute your other classes, and your logic is divided (some in the user control, some in a class). Enter lambdas.

Data-binding expressions are somewhat restrctive in that they can only evaluate DataBinder.Eval and DataBinder.Bind. DataBinder is the context of the expression. However, you can create a new context by writing an inline lambda, like this:

() =>
{
  string url =3.  Somehow, we have to cause this method to be invoked.

My suggestion is to write a server-side method for invoking the lambda.

public delegate string DbExprDelegate();

public static string DbExpr(DbExprDelegate lambda)
{
  var obj = lambda.Invoke();
  return obj;
}

To get the type system to go along, you have to define a delegate type for the lambda. In my case, I knew I would be taking no arguments and returning no strings. For more complex cases you may be able to make good use of generics and type inference to write a more useful generalization. Since lambdas are implicitly convertible to compatible delegates, you can then use the static method DbExpr in your data binding expression to invoke the lambda. I defined DbExpr in my web part class, but I could have put it just it just about anywhere because my user control has no reference to the web part object that loads it, which requires my DbExpr to be static. In other contexts where data binding expressions are used, you may have references to instance objects in your context and may not need to make your DbExpr static.

Finally, we now have the plumbing we need to make the data binding expression work:

<%@ Assembly Name="MyAssembly, etc, etc." %>
<%@ Import Assembly="MyAssembly" Namespace="MyNamespace" %>
 
<%#
MyWebPartControl.DbExpr(() =>
  {
    string url = ((SPListItem)Container.DataItem)["WebPage"].ToString();
    string toks[] = url.Split(new string[] {", "},
                              StringSplitOptions.RemoveEmptyEntries);
    return String.Format("{1}", toks[0], toks[1]);
  })
%>

  1. SPListItem)Container.DataItem)["WebPage"] .ToString().Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries []
  2. Of course, the term “server-side” here doesn’t imply that inline expressions are executed on the client – they aren’t. It’s just a way to distinguish between code organized into class libraries and inline expressions embedded into ASP.NET files, like user controls. []
  3. SPListItem)Container.DataItem)["WebPage"].ToString(); string toks[] = url.Split(new string[] {", "}, StringSplitOptions.RemoveEmptyEntries); return String.Format("{1}", toks[0], toks[1]); }

Now you can see more clearly what it is you’re doing, and as an added bonus, you can actually set breakpoints on each individual statement and inspect local variables (an option that’s unavailable with chained expressions).

There’s a problem, though. The result of this expression is a lambda, not a string. When the page is hit and the server tries to compile this, it may fail. Even if it didn’t, the rendered result would not be desirable ((the lambda’s .ToString() method would be called, and the result would be what the end-user would seee []