We are pleased to announce the release of V4.1.2009 of the Cloud-2-Relational Query Engine.
What is it?
Our Query Engine will allow you to write SQL that will be executed against both a cloud table storage provider as well as most relational database engines.
We all know the benefit of an RDBMS is the ability to write sophisticated DML to extract data. Although these scale fairly well, to store hundreds of millions of records requires special attention or your performance will suffer. Most cloud storage solutions have the ability to store zillions of records (well at least in theory) but don’t really support joins, this is a real problem if you want to normalize your database.
This is where our product comes in. The best of both worlds, the ability of a cloud table provider to store zillions of orders and the ability to join those orders with a much smaller lookup table such as OrderStatus
You simply write a query such as:
select rdbms.Status, cloud.OrderNumber, cloud.OrderAmount from status rdbms, join (Select OrderNumber, OrderAmount from myCloud.orders where UserId = @userId) as cloud on cloud.OrderStatusId = rdbms.OrderStatusId
We are still working on enforcing referential integrity however once we do that we will have the best of both worlds. Performance and Scalability of large scale cloud storage and flexibility of a RDBMS.
-ec
In my ChaosFilter project, I'm factoring all the text and strings into a resource class. The intent is to allow for customization by the end user for different installations and possibly translation at some point. My solution is to place all my text into a class with properties that figure out how to get the text based based upon a unique key and context (which company/application they are running in). Currently these are stored in the database and then loaded into a cached dictionary object. This appears to work very fast, however with my architecture and a bit of code gen this could easily be replaced by more traditional resources.
In the past it's been a pain the a** since I needed to create the label, put the marker into my class file then insert the field into the database. A better solution certainly exists. My solution is to build a DXCore custom refactoring. The idea would be if I'm in a C# class within a string literal or an ASP.NET page within some static HTML, I could hit the refacting key and and take that text and convert it into a message or a simple label. The difference being a label is only a few words where the message could be sentance or two. For larger blocks of text I have a different approach.
My Solution
For a ASP.NET page:

For a C# code file (in a library assembly or code behind):

Then to enter the text:

So how was this done? Actually it was fairly trivial, I built part of it early this week in a couple hours, the rest this morning. Probably < 4 hours for the whole thing and I haven't built a plugin for a couple years.
Getting Started
This link does a much better job than I could to show the basics of creating a DXCore plugin, but unless I missed it, it didn't cover too much about creating custom refactorings.
http://community.devexpress.com/forums/t/68994.aspx
So assuming that you have the frameworks setup for your plugin (I'm going to skip a few steps not relevant and found elsewhere), here's what you need to do:
1) Create a new DXCore Plug for your refactoring:

2) By default the Refactoring Provider that you need to create a custom Refactoring is not in the toolbox, it can be added by "Choose Items" and selecting the RefactoringProvider

3) Once you add that, drop that onto your custom design surface for your Refactoring plugin, it should look something boring like:

4) The click on Properties for your component and add appropriate values:

5) Now go in and click on the highlighed events to build up your stubs:

6) Finally go in and add your code (painting code from: http://tinyurl.com/5a3pe2):
private bool _handlingEditorForegroundPaint = false; private SourceRange _previewRange; private DevExpress.CodeRush.UserControls.CodePreviewWindow _previewWindow = null;
// DXCore-generated code...
#region InitializePlugIn #region FinalizePlugIn
private void ConvertToCustomCaption_Apply(object sender, ApplyContentEventArgs ea) { var customLabel = new ui.CustomCaption(); ea.Element.SelectFullBlock(); customLabel.ShowWithString(CodeRush.Selection.Text, CodeRush.Caret.ScreenPosition); if (!customLabel.Cancelled) ea.Selection.Text = string.Format("Customization.Captions.{0}", customLabel.LabelKey); }
private void ConvertToCustomCaption_CheckAvailability(object sender, CheckContentAvailabilityEventArgs ea) { ea.Available = CodeRush.Caret.InsideString && ea.Element.InsideClass; }
private void ConvertToCustomCaption_HidePreview(object sender, HideContentPreviewEventArgs ea) { if (_previewWindow != null) { _previewWindow.HidePreview(); _previewWindow = null; }
_previewRange = SourceRange.Empty; if (_handlingEditorForegroundPaint) { _handlingEditorForegroundPaint = false; EventNexus.EditorPaintForeground += new EditorPaintEventHandler(EventNexus_EditorPaintForeground); } }
private void ConvertToCustomCaption_PreparePreview(object sender, PrepareContentPreviewEventArgs ea) { PrimitiveExpression ele = ea.Element as PrimitiveExpression; if (ele != null) { _previewRange = ele.Range.Clone(); EventNexus.EditorPaintForeground += new EditorPaintEventHandler(EventNexus_EditorPaintForeground); CreatePreviewWindow(ea, "Customization.Captions.[New]"); } }
private void CreatePreviewWindow(PrepareRefactoringPreviewEventArgs ea, string codeToPreview) { _previewWindow = new CodePreviewWindow(ea.TextView, _previewRange.Top); _previewWindow.AddCode(codeToPreview); _previewWindow.ShowPreview(); }
private void InvalidatePreviews(RefactoringPreviewEventArgs ea) { if (_previewRange.IsEmpty) return;
int doubleSpaceWidth = ea.TextView.SpaceWidth * 2; int textViewLineHeight = ea.TextView.LineHeight; Rectangle previewRect = ea.TextView.GetRectangleFromRange(_previewRange); previewRect.Inflate(doubleSpaceWidth, textViewLineHeight); ea.TextView.Invalidate(previewRect); }
void EventNexus_EditorPaintForeground(EditorPaintEventArgs ea) { if (_previewRange.IsEmpty) return;
using (StrikeThrough strikeThrough = new StrikeThrough()) { strikeThrough.TextView = ea.TextView; strikeThrough.FillColor = Color.Red; strikeThrough.Range = _previewRange; strikeThrough.Paint(ea.Graphics); } }
The "thingy" that let's me enter the text is just a simple WinForm represented by ui.CustomCaption, I won't bore you with that implemetentation since it is fairly tightly coupled intergrated into my architecture.
Enjoy!
-ec
OK - maybe everyone else knows this, but after about a year of getting so-so support for intellisense in Javascript I downloaded the latest hotfix and hoped that this would fix it...it did not. Since I have a very unhealthy addiction to Intellisense I figured out it was time to do a little troubleshooting and get this to work. When adding the the script tags to my page to get intellisense, my Error List now contained the message:

Error updatign JScript IntelliSense: [SOMEPATH]\Temporary Internet Files\Content.IE5\[XXXX]\[XXX].js 'jQuery' is undefiend @ 9.1
So I figured if I could make this error go away chance are pretty good IntelliSense would start working again. What I found is if you use the absolute path /FOO/FEE.JS in your script tag you get this error message. If you don't and use a relative path ../FOO/FEE.JS all is well.
One other thing I found while searching the web (sorry I forgot the site so I can't give the person credit) is to get your Intellisense to work when using Masterpages
 This allows for the design time to pickup the script file, but at run time the file won't be duplicated, especially since my JS files stored as a resource in. I have my JS files compiled as an embedded resource and for some reason, adding those embedded resources to the ScriptManager, Scripts sections doesn't allow IntelliSense to add the files as you would expect. Maybe in another year I'll get around to troubleshooting that, time to get some work done!
-ec
Early on in my career I was mentored on deferring execution. This was in a language called FORTH and the idea was build your program structure and abstract the details into WORDS to be filled in later. Repeat until complete. This simple process still holds true today in OO languages like C# where I do most of my work.
Now back to why I like Silverlight/WPF, as I'm just starting to get beyond the basics, the more I'm starting to see that this is an extremely well thought out architecture. As I'm developing my functionality I can easily "defer execution" or really in this case, care zero about the style and then go in later and make it pretty. Or if I'm really lucky find someone that knows what they are doing to give it a polished look. Although the same can be done with HTML and CSS, this just seems like it's just a bit cleaner and since we are targetting only one type of client (Silverlight or WPF) instead of the different browsers the results are much more repeatable.
The other thing I'm really impressed with is the separation of UI and code behind. Although time will tell on the actual business value (read ability to maintain and extend) it seems like the ability to create CLR instances in the XAML and then glue everything together with dependency properties, just feels good to do.
Now back to getting some work done with this!
-ec
In all my web sites my pages inherit from a custom base page that inherits from System.Web.UI.Page and overrides OnError. This method then uses Server.GetLastError() to get the exception generated by the offending code. At this point, it's probably too late to do anything about it, but at least I can take a snap shot of the current user context, log that information present a friendly message to the user. Although the bug made it into production at least it's not happening 200 times a day and I don't know about.
A good portion of my site is driven by web services via AJAX and as I start to implement Silverlight for a few sophisticated UI components, I'm relying more and more on web services. My problem until now was I didn't have any sort of catch-all that notified me about problem in a web service call.
After a bit of research I found something called a SoapExtension in the System.Web.Services.Protocols namespace.
This provides calls at different points in the processing of the soap message:

We can implement some functionality in the AfterSerialize stage. If we detect a non-null value in the message.Exception property it's probably safe to assume something bad happened within the web service.

The final step is to register this in the web.config file.

In addition SoapExtensions can be associated with specific methods via attributes. This might be interesting to provide an interesting solution for attaching custom authentication and authorization.
-ec
I've finally found a good excuse to implement something using Silverlight 2.0 within my web product. After spending about 3-4 hours attempting to get my Silverlight app to talk to a local web service, I found out something that hopefully will save you some time. First a little about my environment. I'm using IIS 7.0 on a 64 bit machine. I have IIS setup with two sites for my Silverlight development, the first hosts my web service, the second hosts the web site containing my Silverlight application. I have my hosts file setup as follows
127.0.0.1 webservice 127.0.0.1 website
Then in IIS I bind the the web sites to those host names.
After setting up the clientaccesspolicy.xml file in my webservice site to allow Silverlight to access I just couldn't get my Silverlight app to talk to my web service. I tried this in both IE and Firefox with no luck. After doing a little testing, I found it worked when I used the development web server (I think this was formally called cassini) it also seemed to work when when I used the host name "localhost". Next I fired up fiddler and watched the network traffic. Anytime I used cassini or local host, the clientaccesspolicy.xml was downloaded and the call to the web service succeeded. If I tried this through my site, no request was made.
After trying a number of things I found I was able to get this working by opening the security settings within Internet Explorer
Tools->Internet Options->Security Tab, then click on Local Intranet and add my two sites. This seemed to do the trick for both Internet Explorer and Firefox.
Hope this saves you a bit of time
-ec
I have the need in my application for users to upload many different types of documents and images. Currently I have two ways of doing this; the first is to save to a set of directories organzied by user in a file system, the second is in the data base. Neither of these are really ideal for many reasons that I'm sure you recognize. To resolve this issue, I built a component that extends the ASP.NET file upload control to allow you to save files to the Amazon Simple Storage Servce (S3). I've released the source code and component with an open source license, so you can download this and use in your projects as well. The download as well as documentation can be found at http://downloads.slsys.net/S3FileUpload/Default.aspx.
Enjoy and feedback is appreciated!
-ec
I've built some ASMX web services (yes these should be converted to WCF, but they work for now). I'm starting to use these as Script Services for some ASP.NET Ajax Enabled pages. I ran into a problem where some of the "stuff" I didn't want to have happen in some properties on the objects returned by the server were getting executed even though they were marked as [XmlIgnore()] which disables them for SOAP tASMX type web calls. Apparently when the returned objects get serialized as JSON for a script service, they ignore the [XmlIgnore()] tag, which I guess makes sense but is rather inconvenient, in that I need to go back and do a manual search & change. Within the using System.Web.Script.Serialization namespace there is another attribute you can decorate your properties with called [ScriptIgnore()] that seems to do the trick.
-ec
Annoying VS.NET "Feature"
I have a fairly large ASP.NET application that has a large number ASP.NET WebParts built as Custom Controls (150+) in a compiled assembly . I've been getting a little annoyed with VS.NET (I'm using 2008 right now, but saw the same behavior in 2005) where after I get done compiling I have to wait 20-30 seconds while VS.NET does ?something? and freezes the UI (can't ?someting? this be done in a worker thread). Anyway I think I've finally figured out what's up, it would appear anytime I open anything that requires a designer (including an ASMX page) the tool box get's populated with all the custom controls as part of my project. It would seem as soon as the tool box is populated it needs to be refreshed and that's what's taking the 20-30 seconds. So therefore if I don't open anything requiring a designer, I'm OK. I think I've gotten used to this for ASPX and ASCX pages since they normally open up in the HTML view, but I'm still clicking on ASMX and Services design surfaces and end up shutting down VS.NET and restarting without a design surface open.
Maybe my project isn't typical, but it sure would be nice if I could use design surfaces at some point.
-ec
Upgrading .NET FX 2.0 to .NET FX 3.5 and LINQ
After recently upgrading a web project from the 2.0 framework to 3.5 I attempted to use the new language feature LINQ (actually found a really good use for I'll blog about later) however I ran into a problem where it wasn't recognizing the LINQ syntax...after a bit of research I discovered the following, for the ASP.NET compiler to recognize the syntax I need to add the following chunk of xml to my web.config file. Not sure how this works with the compiled ASP.NET apps and my CI environment, if I need to do anything else I'll post it...
</system.web> ... <system.codedom> <compilers> <compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <providerOption name="CompilerVersion" value="v3.5"/> <providerOption name="WarnAsError" value="false"/> </compiler> <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4" type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <providerOption name="CompilerVersion" value="v3.5"/> <providerOption name="OptionInfer" value="true"/> <providerOption name="WarnAsError" value="false"/> </compiler> </compilers> </system.codedom> ... <system.webServer>
Make sense if you think about it...
-ec
Upgrade to .NET FX 3.5 - Assembly Binding I've officially converted my main ASP.NET application from 2.0 to 3.5 this morning overall it was very painless, for the most part, just adjust the class libraries to use the .Net Frameworks 3.5, and modify web.config entries from System.Web.UI.Extensions, Version 1.0.61025.0 to System.Web.Extensions, Version=3.5.0.0. The problem I ran into was that some of the control libraries I was using were compiled against the 2.0 framework. Adding the following keys to the bottom of my web.config files clean that up. <configuration> .... <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/> <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/> <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
-ec
VS.NET 2008 & VS.NET 2005 Solution Files
I recently made the move to Beta 2 for my main project and so-far-so-good, I haven't made the move to the 3.5 framework yet, I probably will as soon as I get the RTM later this month. I'm being a bit cautious and not installing and beta components on my build server so I did a little research and found this article on information for working with your projects in both VS.NET 2008 and VS.NET 2005 concurrently.
http://west-wind.com/weblog/posts/122975.aspx
Basically just make a copy of your solution file, then change the "Format Version" and "# Visual Studio"

ProjectName_2005.sln

ProjectName_2008.sln
From what I can tell so far, the actual project files just aren't a problem.
-ec
Hi, My name is Kevin and I'm a VS.NET Junky
Now what do I mean by that? Well, I'm addicted to the Visual Studio .NET product line, I can't live without it, but it's starting to bring me down and I'm still looking for the high I got from using Visual Studio .NET 2003. As with any humor what makes it funny is a small grain of truth. I don't mean this to be negative, but sometimes you just need to rant. Before I start with the negative, my mom always taught me to never say anything negative without positive comments first. Boy is there a lot positive to say, this latest round of products from Microsoft fundamentally changed the way we developed web application, in such a positive way it's hard to put in to words. I could go on for a long time on all the software I have in production right now that was written using Microsoft .NET technology. When it comes down to it, us as developers aren't really here place judgment on our development tools, we are here to use the best tools out there to satisfy our customers’ needs and frankly there aren't any tools that compare.

Now to the rant, well for the most part I have two main problems that are really starting to drive me nuts, first is performance and the second is VS.NET crashing. Another side bar please, I've been in this industry since the early ninety’s and developing programs since the early eighties we've come a very long ways. I remember a couple of multiyear long projects I worked on in the mid to late nineties. These were VC++ apps that literally to 30 to 45 minutes to compile each code-build-link-test cycle, some of us built some test harnesses to cut this down, but still it took 3 to 5 minutes. As I continue my rant looking back at those projects really puts things in perspective.
So what do I mean by performance issues, I have what I think is a fairy high-end developer machine, not like this monster machine that Scott Hanselman put together (oh yes - I will have a quad core box sitting under my desk by the end of the summer) but a decent machine none the less, I have a Core 2 Duo running at 2.13GHz with 4GB ram and a decent SATA hard drive, I've also got a USB drive I'm using to leverage ReadyBoost on my Vista machine. Here is a link to a better description of my setup. I'm currently working on a fairly large C# solution with about 25 projects and 4 web applications. The application was written so that the user interface is a collection of Custom Controls or more specifically WebParts so each time I make updates I need to compile my control libraries or business objects libraries. If my system has recently been rebooted I can usually do the edit-compile-test cycle in about 15-20 seconds, that includes the ASP.NET page recompiling with the new control library. I have to admit, when you think about all the work it's doing, that is really incredible. With this type of edit-compile-test cycle you can really achieve the state of flow as describe in the wonderful book PeopleWare productive projects and teams, a classic must read. I have a terrible habit of working on too many things at once, I'm lucky, in that I can very quickly context switch however this generally results in a number of applications being open at one time on my computer. After about 3-5 days of working on my Vista machine (for some crazy reason I installed Vista Ultimate, might that be part of the problem?) my compile times slowly start creeping up to where they are starting to approach 45-60 seconds. In reality this just doesn't seem that long however it's just long enough to interrupt the "flow". I think the thing that really makes my blood boil is when I'm watching the output pane in VS.NET and it says the compile completes, its 100% complete with zero errors, then, as I usually run my computer with task manager open, that little green bar sits at about 50%-75% VS.NET is non-responsive and I usually say something to my computer like..."That's OK, I'll just sit here and wait, no problem I don't have anything better to do...are you finished?...are you finished?" (I get some strange looks from my better half, but I think she is getting used to it) then about 15-20 seconds later I can see if what I did actually worked. Alright again only about 15-20 seconds but it certainly blows-the-flow. That closes out the first part of my rant...in all reality, what VS.NET does is incredible, but the extra 30 seconds is just enough to let my mind wonder, check my emails, IM etc... (ding...maybe that's the real problem I have AADD and should look to fix my compile time issue with medications, trade one addition for another). One thing that I try to do to "keep-the-flow" going is with an excellent tool called TestDriven.NET this get's my edit-compile-test time down to a matter of a few seconds when I'm working on my business logic, if you aren't using this why not? In full disclaimer, I have CodeRush and TestDriven.NET plug-ins installed, I don’t think they are the problem. My prior machine was a 3.0GHz Pentium D and 3GB RAM, I installed Vista Business and the VS2008 Beta 2 (not in a Virtual PC). I don't plan on installing any other software on that machine and will see how it performs.
Rant number two...this one won't be nearly as long, about every 30-50th compile, as soon as I see that "Build Successful" message in my status bar, within a blink of eye Visual Studio disappears from my screen. No error message no log entry...nothing, it's just gone. I start it up and load my project (which takes between 2-3 minutes) and have never lost any work, but my solution settings (such as which files are open etc...) get lost. Really a little annoying. Whenever I get a free 4-5 hours I'm going to repave the machine and only install VS.NET and the key tools necessary for doing development, this time I mean it for sure, really only my development apps.
There, I got that off my chest after looking at the good the bad and the ugly, the reality of it for the size of our solutions and all the competing junk I have on my machine, I should be happy these compile in 5 minutes and I'm probably being greedy, but as with most developers I like to rant and complain.
Bottom line, thank you Microsoft for feeding my habit and providing me with a great (but not perfect) set of tools to write software to keep my clients happy and thus pay my bills, let’s see if we can do it a tad better in Orcas.
-ec
Exploring SharePoint 2007 with PowerShell
The more I work with SP2007, the more I get pumped about the technology. Although there is a lot you can do right out-of-the-box, the programming model behind this really allows it to be a great framework for any development platform.
To get started programming, you probably want to get an idea of how the Object Model works, a real simple way to do this is with PowerShell. I have an SP2007 dev server I setup that I installed PowerShell & PowerShell IDE on. Once you do that, just get a hold of the SP2007 SDK documentation, this will give you an idea of the structure of the Object Model then start playing! The following screen shot should be enough to get you going:

Obviously this same concept would work to exercise any object model!
Enjoy!
- ec
Custom WebParts in SharePoint 2007
Creating a custom WebPart in SharePoint 2007 isn't all that terribly difficult, just a few basic steps that may not be completely obvious...in addition if you want to deploy your WebPart on SP 2007 it may contain some additional resources such as gif's or java scripts. Wouldn't it be nice if you could just deploy one assembly with everything you need? Well that's possible so let's do that as well...
- To start out, just create a new VS.NET 2005 class library project and add a reference to "System.Web".
- Go ahead and setup a reasonable sounding Assembly Name and Default NameSpace, these will be important when registering your component with Share Point 2007.
- While your are changing your project settings, find the Signing Tab and make sure "Sign the assembly" is checked. You will then need to go ahead and create a new KeyFile. So far straight forward right?
- Now let's add our web part, to do this simply add an class to your project.
- The code in your web part should look something like Not a example of good coding but that isn't the point
:
using System; using System.Runtime.InteropServices; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Serialization; using System.Reflection; using System.Data; using System.Data.SqlClient; using System.ComponentModel;
namespace SoftwareLogistics.SharePointTest {
[ Guid("72a24b71-f3a9-4fee-9272-4f3c27c87559")] public class SampleSP2007Part : System.Web.UI.WebControls.WebParts.WebPart { System.Web.UI.WebControls.DataGrid grdTime;
protected override void CreateChildControls() { Image img = new Image(); img.ImageUrl = Page.ClientScript.GetWebResourceUrl(this.GetType(), "SoftwareLogistics.SharePointTest.Images.Target.gif");
grdTime = new System.Web.UI.WebControls.DataGrid(); string dsn = "server=??????;database=??????;user id=????;password=?????";
SqlDataAdapter da = new SqlDataAdapter("select top 5 * from usv_time_tracking order by start_date desc", new SqlConnection(dsn)); DataTable tblTime = new DataTable("My Time");
da.Fill(tblTime); grdTime.DataSource = tblTime; grdTime.DataBind();
Controls.Add(img); Controls.Add(new LiteralControl("<br/>")); Controls.Add(grdTime);
base.CreateChildControls(); }
protected override void Render(HtmlTextWriter writer) { writer.Write("<h4>Hello World!</h4>"); base.Render(writer); } } }
Before installing this to SharePoint 2007, let's complete this section by talking about what we need to do to embed the resources with the assembly.
- Create an Image directory within your project and copy the Image there:
- You can see that the name including the NameSpace is "SoftwareLogistics.SharePointTest.Images.Target.gif" (Case is important here)
- Once you copied the image there you need to make sure you click on "Properties" and then set the Build Action to "Embedded Resource" for Target.gif, very important to do this...
- Now open up your "AssemblyInfo.cs" file that is in the Properties folder of your project. Add a line to it similar to
[assembly: WebResource("SoftwareLogistics.SharePointTest.Images.Target.gif","image/gif")
-
You will also need to add using System.Web.UI; to the top of your AssemblyInfo.cs.
-
Finally in the code you can set the url of the image as: img.ImageUrl = Page.ClientScript.GetWebResourceUrl(this.GetType(), "SoftwareLogistics.SharePointTest.Images.Target.gif");
Now your assembly is ready to go all you need to do is turn that into and assembly and your are ready to incorporate it into your SharePoint 2007 site, you can even us this as a WebPart or even a standard Server Control on any ASP.NET 2.0 site.
To install the the component on the SharePoint2007 server you need to do the next couple of steps...
- First we need to get our component into the GAC so just drag it into the file pane for Windows\Assembly, you can see the my file here:
- Make a note of the Public Key Token, you will need that to register your part with SharePoint, you can also right mouse click on the assembly click on Properties and copy the Pulbic Key Token from there.
- The final step to make it appear as a "potential" web part within SharePoint is to register the component in the Web.Config file. So find Web.Config for the SharePoint instance you want this work with and open it in your favorite XML editor.
- Find the section labeled "SafeControls" and add the following line (you can always just copy one of the existing lines and fill in your information.
<SafeControl Assembly="SoftwareLogistics.SharePointTest, Version=1.1.0.0, Culture=neutral, PublicKeyToken=8220d66cd77f3b8d" Namespace="SoftwareLogistics.SharePointTest" TypeName="*" Safe="True" />
At this point SharePoint knows about your WebPart, but you'll need to make it part of the Gallery so open up your SharePoint site and do these final steps
- Click on "Site Actions" and then "Site Settings"
- Within the "Galleries" section click on "Web Parts"
- Click on New, if all went well you should see the part you created within the list, if you don't see it there, go ahead and reset IIS.
- Put a check mark next to your new web part and then click the "Populate Gallery" button.
At this point your web part is ready to be included just like any other WebPart.
Happy Coding!
- ec
SharePoint 2007 - It's finally all coming together!
I remember in the very early days of .NET they had a cool demo of how to build a portal in ASP.NET, this was called "I Buy Spy" from what I understood went on to be DOTNETNUKE, I was excited about the concept of configurable content within the portal, it had all the right concepts, adding tabs, little widgets you could configure etc... These were really just Web Controls (ASCX) or Server Controls (compiled DLL's). My third version of "The Chaos Filter" used this concept extensively.
Then with ASP.NET 2.0, they introduced the concept of WebParts, this was nice however you had to build up a set of scaffolding and use the provider model to use these within your site (at least as pure web parts). Not terribly difficult but it limited your deployed options. At the time SharePoint 2003 had something called "WebParts" as well, extremely similar in both appearance and function, however these "WebParts" were not the same thing as those created with ASP.NET 2.0. Very disappointing (and confusing), SharePoint 2003 web parts actually came out first, and I assume that Microsoft kept the name since it seems to fit this concept so well and the intent with ASP.NET 2.0 web parts was that they would work with SharePoint 2007.
Version 3.0 of the product really defined and flushed out the data model and workflow engine however, I just wasn't very happy with the presentation layer in ASP.NET 1.1 using the ASCX's and custom controls. With the introduction of the ASP.NET 2.0 I started on version 4.0 of "The Chaos Filter", this time I focused on an architecture that was built from the ground-up to use web parts and leverage the existing data model and workflow concepts that make the Chaos Filter unique. This architecture relied heavily on code generation from a product called CodeSmith, templates where created to not only create a simple DAL that mapped to tables in the database, but it also created two web parts (master/detail) for each tables. This obviously doesn't mean that you can generate 100% of the application, however it does mean that it can very rapidly give you web parts that work out-of-the box that you can customize. Anytime I hear "You can build your hole site in just three lines of code" my spider senses tell me to watch out! This solution is really intended to put in place the framework and plumbing that you can open up in your development environment and make it do something useful.
So here we are, SharePoint 2007 was released last November, what does this give us that we really didn't have before? We now have the ability to easily create little "chunks" of functionality in the form of "WebParts" that can be wired up to create applications. So with the data model defined in V3.0 of my product, the architecture to include code generation defined in V4.0 of my product, and a mature framework in SharePoint 2007, it's time to start figuring out how to package these concepts into something that will provide value.
-ec
ASP.NET Under Vista
Vista is deployed with IIS 7.0 a cool feature that wasn't available on XP is the ability to create multiple web sites. This means you can can configure IIS to look at the host name and map that to a particular web site...I explain...
First find and open your hosts file, this is in in \Windows\System32\Drivers\Etc add a couple of entries that point back at your local machine (127.0.0.1)

Next open up IIS and create a new web site, in the Host header section enter the name of "virtual host" you entered in your hosts file (also don't forget to set your app pool up to use the "Classic ASP.NET" pipe line mode)

Now you can browse to the site you are developing with just http://plinks instead of http://localhost/plinks

Although this seems like a fairly small deal, if you are working on multiple projects it's nice to keep things organized a little better not to mention a few less key strokes bringing up the page.
-ec
Web Resources in a Different Assembly
A really cool feature in ASP.NET 2.0 is the ability to embed resources such as images, css and js files within your compiled source, just like you can in a Windows application.
I have a pet project I've been working on for a number of years, it's something that when the time is right I want to try to market. For now it's a good place to "play" with the new technology so I can be effective when I implement it for my clients.
Embedding resources within an assembly makes considerable sense for creating an easy to install deployment package. Within a short amount of time I was able to follow the sample code within this sample.
|
What I really wanted was the ability to place my resource files into a seperate assembly to facilitate having different images for different deployments. For some reason if I put the image in the same assembly as the Custom Control that displayed it, everything worked fine. As soon as I moved the image into it's own assembly, I get that lovely red x showing that the resource could not be found on the server. |

|
To solve this problem, I simply created a new class within my resource assembly and in then in my call to "GetWebResourceUrl" instead of passing the type of calling object I passed in a type within resource assembly.
node.Image = Page.ClientScript.GetWebResourceUrl(typeof(ChaosFilter.Images.Stub), "ChaosFilter.Images.Tree.Add.gif");
Once I did that I got the image as I expected it.

So here is my simple resource assembly that could be used to swap out the images, it just needs the simple class ChaosFilter.Images.Stub and life is good

- ec
ASP.NET 2.0 Menu Control Limitations
Currently in one of my projects we decided to move from a custom tab/menu navigation scheme to one that exclusively uses the ASP.NET 2.0 Menu Navigation control. At first I thought, no big deal, we wrote custom providers for membership, roles and a site map. These were slightly more complex due to the fact that we are using this with the concepts of a portal. A user can belong to different portals, they may have different roles within each portal and each portal may have a unique site map.
This worked extremely well using only the core features of the provider model, however when we wanted to use the actual ASP.NET Menu Navigation control (which is actually quite good) we found that for our needs on this project it was too tightly coupled to FormsAuthentication model within ASP.NET 2.0.
What we wanted was to secure access to the site via the site map file as well as use this to build menus that only reflect what the user has access to. The ASP.NET Menu Navigation control only uses the SiteMap file to show/hide menu items within the tree. In addition other than at the top node, showing/hiding menu nodes is controlled by the authorization sections of the web.config file. That is to say unless you use the authorization seconds within the web.config file, the roles attributes within the SiteMap are ignored. Since our application wants to control access to pages within the SiteMap so we can have multiple site maps per web site, this solution didn’t work for us. In addition our site map is not exclusively mapped to pages within our system. It is possible for our site map to actually call a feature within the page. If we want to lock down specific actions in the page, but not the complete page this will become a problem.
Our solution will be to not use the built in method of binding roles to menu nodes from the SiteMap control to the roles for the current users that is built in to the ASP.NET Menu Navigation control built from our custom site map provider, but modify our site map provider to build up the menu control each time it’s needed for each user based upon their roles. The problem with this is that we take a performance hit.
One possible solution (not possible within the scope of the current project) would be to inherit from the ASP.NET 2.0 Menu Control and provide additional behavior to exclusively use the roles from the SiteMap file.
Obviously that part of the solution that is not discussed was to make sure that when a user attempts to perform an action on a page from the menu control, it is authorized since it may be possible for the user to enter a URL without clicking on a menu control. This would be normally handled by the authorization section within the web.config file, our approach is to do a lookup within the site map file to detect unauthorized actions.
FOLLOWUP 2/4/2007 - Since a considerable number of the users of the site are using Safari on a Mac, we need to replace the ASP.NET 2.0 Menu Control we used a JavaScript menu strategy instead.
|