Tag Archives: ASP.NET

Recycle IIS App Pool from Script

My colleague, Carlos Fernandez, sent me this CSCRIPT command for recycling the an IIS application pool:

%windir%system32cscript.exe c:windowssystem32iisapp.vbs /a "SharePoint – 80" /r

Tired of manually recycling the app pool each time you make a code change to your SharePoint web part?  No problem, add the following command to the post build events in Visual Studio.

“Submit” ASP.NET and SharePoint

One of my developers and I ran into an interesting problem today – we’d migrated a web site over to SharePoint 2007 (using a popular content migration tool) and found that all page postback calls in SharePoint were giving JavaScript errors, specifically:

Object doesn’t support property or method.

Turns out that our master page and page layouts contained input controls (text boxes) with name/id as “submit”.  Use of this reserved name sent ASP.NET’s JavaScript code into a tailspin and wrecked havoc with any postback submissions.

So, when you develop web sites in ASP.NET and/or SharePoint, be inventive with names for your buttons, text boxes and hidden fields – how about btnSubmit 😉

I read somewhere else that naming the main ASP.NET form “default” is a no-no also.

Invocation of SOAP Web Service gives 500 Internal Server Error

Picture this situation:  It’s now 3am, start of business is deadline day for development of your project, and you’ve been working for the last 7 hours on a web service client bug; where dynamic invocation of the service, via SOAP 1.2, causes the server to return an HTTP 500 Internal Server error.  The air conditioning kicked off at 7pm and now everything you touch is sticky from sweat and frustration.  This was me.

After staring at the code responsible for creating my SOAP envelope and the HTTP post code, and trawling through Google, I finally found a solution.  Apparently, the raw server response is buried in the System.Net.WebException, thrown by .NET, and with some code added to the exception catch block it is possible to find out what really went wrong.

Here’s the code:

   1: private static string PostSoap(string url, string soapEnv)
   2: {
   3:     try
   4:     {
   5:         string result;
   6:         byte[] postData = Encoding.UTF8.GetBytes(soapEnv);
   7:         HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
   8:         if (null == request)
   9:             throw new WebException("Failed to create WebRequest object");
  10:         request.Method = "POST";
  11:         request.ContentType = "application/soap+xml; charset=utf-8";
  12:         request.ContentLength = postData.Length;
  13:         request.UserAgent = "DynamicFormWebPart";
  14:         using (Stream stream = request.GetRequestStream())
  15:         {
  16:             stream.Write(postData, 0, postData.Length);
  17:             stream.Flush();
  18:             stream.Close();
  19:         }
  20:         HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  21:         if (null == response)
  22:             throw new WebException("Failed to get a WebResponse object");
  23:         using (StreamReader reader = new StreamReader(response.GetResponseStream()))
  24:             result = reader.ReadToEnd();
  25:         return result;
  26:     }
  27:     catch (WebException ex)
  28:     {
  29:         HttpWebResponse response = ex.Response as HttpWebResponse;
  30:         if (null == response)
  31:             throw new ArgumentNullException("Response was null");
  32:         using (StreamReader reader = new StreamReader(response.GetResponseStream()))
  33:         {
  34:             string error = reader.ReadToEnd();
  35:             throw new PSWebPartException(error, ex);
  36:         }
  37:     }
  38: }

 

By the way, the error causing me mental turmoil this evening was because I passed ‘True’ to a boolean parameter, instead of lowercase ‘true’.  What threw me, was the .NET HTTP POST test page, which allows uppercase T and F in boolean values.  I guess I loose such niceties when creating my own lower level code.

7 hours for an upper case ‘T’ – geez, woot.

ASP.NET Web Services, HTTP GET and POST

Since the beginnings of ASP.NET 1.1, Microsoft disabled HTTP GET and POST actions on .NET Framework based web services (for security reasons).  If you want to enable these protocols, add the following XML to the the system.web node in the web.config file:

<webServices>
     <protocols>
          <add name=”HttpGet”/>
          <add name=”HttpPost”/>
     </protocols>
</webServices>

I recommend that you only enable these protocols if your service does not care about security. In my case, I wanted to expose an already public non-rpc service as a web service (with some business logic thrown in) and still enable legacy clients to use this new service without the SOAP overhead.

Deploying a WebPart in SharePoint 2007

This is one of those topics, which I frequently look up, and so what better place to put the information than this blog?  Scot Hillier has explicit instructions in his book (Microsoft SharePoint – Building Office 2007 Solutions in C#) on page 404 to deploy a webpart using a solution package.  The following instructions are an excerpt from his information.

Create a Strong Name Assembly

  1. Create a strong name for your web part (if you have not already done so), using sn-k c:keypair.snk.
  2. Add the key pair file to the project containing your web part.
  3. In the webpart project properties, sign the assembly using the key pair.

Create a Manifest File

  1. Add a new XML file to the webpart project, name this file manifest.xml.
  2. Add the following code to the XML file…
       1: <?xml version="1.0" encoding="utf-8" ?>
       2: <Solution xmlns="http://schemas.microsoft.com/sharepoint/"
       3:           SolutionId="AF597DAB-65D7-4c1a-A012-D04184CA647E">
       4:     <Assemblies>
       5:         <Assembly DeploymentTarget="WebApplication"
       6:             Location="SPDataPart.dll">
       7:             <SafeControls>
       8:                 <SafeControl
       9:                     Assembly="SPDataPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8c9fc716f38d08b2"
      10:                     Namespace="SPDataPart" TypeName="*"/>
      11:             </SafeControls>
      12:         </Assembly>
      13:     </Assemblies>
      14: </Solution>
  3. Change the details in to match your webpart DLL name, strong name, and public key token.
  4. Note: If creating XML solution file is not your thing, Scot talks about a Visual Studio template on CodePlex to make solution file creation easier – link.

Create the Solution Package

  1. Add a new “CAB Project” to the solution, alongside the webpart project.
  2. Add “Project Output/Primary Output” from the webpart project to the CAB project – this adds the webpart DLL to the CAB.
  3. Add “Project Output/Content Files” from the webpart project to the CAB project – this adds the manifest file to the CAB.
  4. Build the entire solution.
  5. Find the CAB file in the bin/[Debug|Release] folder for the CAB project and rename the CAB extension to WSP.
  6. You now have a Web Solution Package.

Deploying Solution to SharePoint

  1. Run the following command on the SharePoint box to install the solution:

    stsadm.exe -o addsolution -filename PathToMyWSPFile.wsp

  2. Open SharePoint Central Administration Console.
  3. Click the operations tab and then Solutions Management link.
  4. Click the solution package listed, which we added in step 1 of this section
  5. From the package options page, click deploy.
  6. Navigate to the top level site containing the web part.
  7. Go to the web part gallery under site settings.
  8. Click the New button.
  9. Check the webpart(s) from the list to add to the site.
  10. You are now ready to add the webpart to web part zones within the site.

Encrypt/Decrypt Web.config Sections

Encryption of sections in my web.config file is a task I am constantly looking up on the Internet, so I thought I’d blog it here.

-- Generic form for encrypting the Web.config file for a particular website...
aspnet_regiis.exe -pef section physical_directory –prov provider
   -- or --
aspnet_regiis.exe -pe section -app virtual_directory –prov provider
-- Concrete example of encrypting the Web.config file for a particular website...
aspnet_regiis.exe -pef "connectionStrings" "C:InetpubwwwrootMySite" –prov "DataProtectionConfigurationProvider"
   -- or --
aspnet_regiis.exe -pe "connectionStrings" -app "/MySite" –prov "DataProtectionConfigurationProvider"
-- Generic form for decrypting the Web.config file for a particular website...
aspnet_regiis.exe -pdf section physical_directory
   -- or --
aspnet_regiis.exe -pd section -app virtual_directory
-- Concrete example of decrypting the Web.config file for a particular website...
aspnet_regiis.exe -pdf "connectionStrings" "C:InetpubwwwrootMySite"
   -- or --
aspnet_regiis.exe -pd "connectionStrings" -app "/MySite"

Thanks to Scott Mitchell for the source of information.

Hosting Microsoft Live.com Gadgets in your ASP.NET Application

OK, this has to be one of the most asked questions about Microsoft Live.com gadgets (except perhaps the question – “Are Vista Gadgets and Live.com Gadgets the same?”) –

How to host Microsoft Live.com gadgets in my own ASP.NET applications?

Sounds like there must be an easy answer for this one…. not exactly.  Microsoft haven’t published the Live.com back end infrastructure as yet, just the means in which developers can use the Live.com site to host their home-brew gadgets.  MS won’t commit to whether they intend to release the gadget framework, leaving custom portal developers without any way to incorporate the vast array of Microsoft gadgets into their sites.

I’m not one for giving up easily, so I trawled the web, and after some time found the answer I was looking for.  It seems that Microsoft made some changes to their gadget framework back in late 2005, which changed how gadgets are rendered with IFRAMES.  As a side effect, the following URL will render a Live.com gadget in your browser (try it):

http://gadgets.start.com/gadget.aspx?manifestUrl=http://gadgets.donavon.net/gadgets/digitalclock.xml&dash=false&view=Custom

Hosting Live.com gadgets in your web site is a simple case of embedding an IFRAME tag with the above URL (change the manifest URL to the desired gadget of course):

<iframe id=”Iframe1″ src=”http://gadgets.start.com/gadget.aspx?manifestUrl=http://gadgets.donavon.net/gadgets/digitalclock.xml&dash=false&view=Custom”

scrolling=”auto” frameborder=”0″ width=”100%”></iframe>

I went one step further and created a custom web part for ASP.NET 2, which should also work for SharePoint 2007 with very little adjustment, below is the code.  Throw it into a class library, add a reference to your web site, and instantiate the GadgetWebPart control.

Presto!

public class GadgetWebPart : WebPart

{

#region Fields

private string _manifestURL = String.Empty;

private TextBox _urlTB = null;

private Button _submitBtn = null;

private HtmlGenericControl _iframeCtrl = null;

#endregion Fields

#region Properties

/// <summary>

/// Manifest URL of web part.

/// </summary>

[WebBrowsable(), Personalizable()]

public string ManifestURL

{

get { return _manifestURL; }

set { _manifestURL = value; }

}

#endregion Properties

#region Methods

/// <summary>Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering.</summary>

protected override void CreateChildControls()

{

// Clear the controls collection.

Controls.Clear();

// Create controls.

_urlTB = new TextBox();

Controls.Add(_urlTB);

_urlTB.Style.Add(“width”, “200px”);

_submitBtn = new Button();

_submitBtn.Text = “Install Gadget”;

_submitBtn.Click += new EventHandler(submitBtn_Click);

Controls.Add(_submitBtn);

_iframeCtrl = new HtmlGenericControl(“iframe”);

Controls.Add(_iframeCtrl);

_iframeCtrl.Attributes.Add(“width”, “100%”);

_iframeCtrl.Attributes.Add(“height”, “100%”);

_iframeCtrl.Attributes.Add(“scrolling”, “auto”);

_iframeCtrl.Attributes.Add(“frameborder”, “0”);

}

/// <summary>Raises the <see cref=”E:System.Web.UI.Control.PreRender”></see> event.</summary>

/// <param name=”e”>An <see cref=”T:System.EventArgs”></see> object that contains the event data. </param>

protected override void OnPreRender(EventArgs e)

{

// Do we have a manifest URL?

if (!String.IsNullOrEmpty(_manifestURL))

{

_urlTB.Visible = false;

_submitBtn.Visible = false;

_iframeCtrl.Visible = true;

_iframeCtrl.Attributes[“src”] =

String.Format(“http://gadgets.start.com/gadget.aspx?manifestUrl={0}&dash=false&view=custom”, _manifestURL);

}

else

{

_urlTB.Visible = true;

_submitBtn.Visible = true;

_iframeCtrl.Visible = false;

}

// Call base version

base.OnPreRender(e);

}

/// <summary>

/// Submit button clicked.

/// </summary>

/// <param name=”sender”>Sender Object.</param>

/// <param name=”e”>Event args.</param>

void submitBtn_Click(object sender, EventArgs e)

{

if (null != _urlTB && !String.IsNullOrEmpty(_urlTB.Text))

_manifestURL = _urlTB.Text.Trim();

if (null != Width && Width.Value > 0)

_iframeCtrl.Attributes[“width”] = Width.Value.ToString();

if (null != Height && Height.Value > 0)

_iframeCtrl.Attributes[“height”] = Height.Value.ToString();

}

#endregion Methods

}

Thanks to Donavon for his post on the following forum thread:  http://microsoftgadgets.com/forums/1478/ShowPost.aspx

Embedding Windows Media and Quicktime into ASP.NET pages

I know there are numerous web sites and blogs about this subject.  Since I had to write some code for “Fred” to render on-line video, and embedding video in web pages can be somewhat fiddly to get right, I figured I’d blog the C# code for my future reference.  If hosting on-line video in your web site interests you, be sure to check out Sahil Malik’s post on the subject.

Below are two examples, which create the HTML for embedding Windows Media and Quicktime sources.  To use this code, compile either or both examples into your ASP.NET project (or into a referenced class library assembly), bung a PlaceHolder on your page and during the load event of your page pass the instance of your PlaceHolder control to the desired method.  The location should either be a relative URL or absolute URL to the hosted video file, which can be a streaming location or an HTTP location.

Embedding Windows Media:

private void CreateMediaPlayerEmbeddedControl(PlaceHolder ph, string location, int width, int height)
{
HtmlGenericControl result = new HtmlGenericControl();
ph.Controls.Add(result);
HtmlGenericControl embed = new HtmlGenericControl();
result.Controls.Add(embed);
// Embed tag.
embed.TagName = “embed”;
embed.Attributes.Add(“type”, “application/x-mplayer2”);
embed.Attributes.Add(“pluginspage”, “http://www.microsoft.com/netshow/download/player.htm”);
embed.Attributes.Add(“name”, “mediaPlayer”);
embed.Attributes.Add(“width”, width.ToString());
embed.Attributes.Add(“height”, height.ToString());
embed.Attributes.Add(“AllowChangeDisplaySize”, “1”);
embed.Attributes.Add(“AllowSize”, “0”);
embed.Attributes.Add(“AutoSize”, “0”);
embed.Attributes.Add(“AutoStart”, “1”);
embed.Attributes.Add(“DisplaySize”, “4”);
embed.Attributes.Add(“EnableContextMenu”, “0”);
embed.Attributes.Add(“Enabled”, “1”);
embed.Attributes.Add(“InvokeURLs”, “0”);
embed.Attributes.Add(“ShowCaptioning”, “0”);
embed.Attributes.Add(“ShowStatusBar”, “0”);
embed.Attributes.Add(“ShowControls”, “1”);
embed.Attributes.Add(“WindowlessVideo”, “1”);
embed.Attributes.Add(“uiMode”, “None”);
embed.Attributes.Add(“src”, location);
// Object tag
result.TagName = “object”;
result.Attributes.Add(“classid”, “clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95”);
result.Attributes.Add(“standby”, “Loading Microsoft Windows Media Player components…”);
result.Attributes.Add(“codebase”, “http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701”);
result.Attributes.Add(“type”, “application/x-oleobject”);
result.Attributes.Add(“width”, width.ToString());
result.Attributes.Add(“height”, height.ToString());
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
}

Embedding Quicktime:

private void CreateQuickTimeEmbeddedControl(PlaceHolder ph, string location, int width, int height)
{
HtmlGenericControl result = new HtmlGenericControl();
ph.Controls.Add(result);
HtmlGenericControl embed = new HtmlGenericControl();
result.Controls.Add(embed);
// Embed tag.
embed.TagName = “embed”;
embed.Attributes.Add(“width”, width.ToString());
embed.Attributes.Add(“height”, height.ToString());
embed.Attributes.Add(“scale”, “tofit”);
embed.Attributes.Add(“autoplay”, “true”);
embed.Attributes.Add(“controller”, “true”);
embed.Attributes.Add(“target”, “myself”);
embed.Attributes.Add(“type”, bo.MimeType);
embed.Attributes.Add(“pluginspage”, “http://www.apple.com/quicktime/download/index.html”);
embed.Attributes.Add(“src”, location);
// Object tag
result.TagName = “object”;
result.Attributes.Add(“classid”, “clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B”);
result.Attributes.Add(“codebase”, “http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0”);
result.Attributes.Add(“width”, width.ToString());
result.Attributes.Add(“height”, height.ToString());
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
result.Controls.Add(new LiteralControl(“”));
}

That’s it…. now if you’re really good, you can detect the client operating system, by looking for the word “Windows” in the user agent string (hint:Request.UserAgent) and calling the correct method above.

I tested the above code using FireFox and IE (Windows and Mac).  Windows Media will play in FireFox if you have the Windows Media Plugin (Windows version ships with latest version of Windows Media Player) installed, and the rendering Quicktime requires the plugin from Apple (duh).

WebResource.axd

Winform applications have been using resources (embedded images etc) for some time.  .NET allows developers to embed binary files into assemblies, which can later be retrieved by code at runtime.  ASP.NET is no exception.  How many times have you written a web control, which requires images, and you’ve had to rely on the client web site, using your control, having the correct images in the right location?  A better solution is to embed the images in the web control assembly and have ASP.NET pull the image at runtime.  This is where WebResource.axd comes in.  WebResource.axd is a build in ASP.NET  web handler that manages the rendering of resourced images on a client web browsers.

The following steps inform developers how to add an image resource to a web control assembly, and then have ASP.NET render the image using WebResource.axd.

1. Add the image to your web control project.
2. In the solution explorer, click the file, and in the property window, change build action to “embedded resource.”
3. Add the following to your AssemblyInfo.cs file in the web control project:
[assembly: WebResourceAttribute(“MyNameSpaces.MyControl.Images.MyImage.gif”, “image/gif”)]
Note:  “MyNameSpaces.MyControl” comes from the default
namespace indicated in the web control project properties. “Images” is a folder in the web control project that contains “MyImage.gif”
.
4. In your control rendering code, you’ll need the following to produce a usable URL for the image:
Page.ClientScript.GetWebResourceUrl(typeof(MyNameSpaces.MyControl), “MyNameSpaces.MyControl.Images.MyImage.gif”)

The above steps produce a URL in your rendered control that looks something like:
/WebResource.axd?d=PhPk80h_UWEcbheb-NHNP5WshV_47UOpWqAOl1_li
UFfN4cNofL74cFlQ1fvpFSf0&t=632573240669964903

Debugging ASP.NET as non-admin (LUA)

See my previous post about LUA, and why it is a good idea.  Today
I managed to get ASP.NET 2.0 to debug correctly, using Visual Studio
.NET 2005 under LUA.  Thanks to Andrew Duthie’s post.  I needed to tweak my system a little, here are my steps in digest (II6 only):

1. Create a new user group (Control Panel, Administrative Tools, Computer Manager, Local Users and Groups), called ASPNETDebug.
2. Add the LUA user to the ASPNETDebug group.
3. Add the LUA user to the IIS_WPG group.
4. Modify the following local account policies (Control Panel,
Administrative Tools, Local Security Policy, Security Settings, Local
Policies, User Rights Assignments):

  • “Adjust memory quotas for a process” – add the ASPNETDebug user group.
  • “Replace a process level token” – add the ASPNETDebug user group.

5. Modify the NTFS permissions on the following directories, and add the ASPNETDebug group with modify permissions:

  • %windows%temp
  • %windows%Microsoft.NETFramework%framework version%Temporary ASP.NET Files

6. Create a new application pool in IIS 6 (not based on any other app pool).
7. Change the identity of the newly created application pool to the LUA.
8. Change the app pool of ASP.NET web site application being debugged to the newly created app pool.