Rob Chartier ~ Contemplation...

.NET, C#, Work, etc.

News






www.flickr.com
This is a Flickr badge showing public photos from Rob & Kat Chartier. Make your own badge here.


Even Quicker Links

August 2010 - Posts

.NET BC : A Lap around WebMatrix; With a dash of Razor

 

Last night most of the DotNetnuke team and I traveled into Burnaby, to the BCIT campus where I gave a real quick (1 hour) presentation on the WebMatrix Beta, and Razor Syntax.

I was happy to see that we had over 60 people attend.  It was awesome to see the turn out on a hot summer evening. 

Download the Slide Deck

There were a number of questions which came up, I will try to remember them all here.

 

Working with Data – the db.Query() execution, can it be parametrized?

@{
var db = Database.OpenFile("SmallBakery.sdf");
var selectQueryString = "SELECT * FROM Products ORDER BY Name";
}
@foreach (var row in db.Query(selectQueryString)){
<tr>
<td>@row.Id</td>
<td>@row.Name</td>
<td>@row.Description</td>
<td>@row.Price</td>
</tr>
}

Yes, you can.  Here is an example.

@{
var db = Database.OpenFile("SmallBakery.sdf");
var Name = Request["Name"];
var Description = Request["Description"];
var Price = Request["Price"];
var insertQuery = "INSERT INTO Products (Name, Description, Price) VALUES (@0, @1, @2)";
db.Execute(insertQuery, Name, Description, Price);
}

What and Who is WebMatrix and Razor targeted to?

Essentially the breadth developer.  Those folks that possibly come from a PHP background or even are new to the development world.  This will allow for them to onboard with a few minor tweaks to existing projects to get up and running as fast as possible.

 

Why is Web Matrix even needed when we have Visual Studio?

The initial thoughts are that this product is going to be free.  It will have a bare minimum feature set targeted to the scripter.  The UI is far simpler than what VS.NET Users are used to.  You could consider it as a a stepping stone into VS.NET.

 

There was some discussion around Razor Syntax and MVC.  Using it as a view engine.  Here are some resources to help with this answer.

http://gurustop.net/blog/2010/07/06/thoughts-on-razor-microsofts-new-asp-net-mvc-view-engine/

and

http://www.dotnetcurry.com/ShowArticle.aspx?ID=561

The topic of LightSwitch came up as well.  Here is the product page

http://www.microsoft.com/visualstudio/en-us/lightswitch

SIMPLEST WAY TO BUILD BUSINESS APPLICATIONS FOR THE DESKTOP, WEB AND CLOUD

Microsoft Visual Studio LightSwitch gives you a simpler and faster way to create professional-quality business applications for the desktop, the web, and the cloud. LightSwitch is a new addition to the Visual Studio family. Visit this page often to learn more about this exciting product.

 

Conclusion

All in all I felt the talk went well.  As usual I went a mile a minute and really tried to slow things down near the end.  Luckily there were enough questions to push us for the full hour.  If you attended feel free to send me feedback and ask questions.  I will do my best to get you the answers – just keep them on topic!

 

 

Resources for the discussion

http://www.asp.net/webmatrix

http://netbc.ca/DNCal/EventDetail.aspx?date=2010/08/24

Sql Scripts - Delete all Tables, Procedures, Views and Functions

In a shared environment you typically don't have access to delete your database, and recreate it for fresh installs of your product. 

I managed to find these scripts which should help you clean out your database.

Use at your own risk.

 

Delete All Tables

--Delete All Keys

DECLARE @Sql NVARCHAR(500) DECLARE @Cursor CURSOR
SET @Cursor = CURSOR FAST_FORWARD FOR
SELECT DISTINCT sql = 'ALTER TABLE [' + tc2.TABLE_NAME + '] DROP [' + rc1.CONSTRAINT_NAME + ']'
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc1
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc2 ON tc2.CONSTRAINT_NAME =rc1.CONSTRAINT_NAME
OPEN @Cursor FETCH NEXT FROM @Cursor INTO @Sql
WHILE (@@FETCH_STATUS = 0)
BEGIN
Exec SP_EXECUTESQL @Sql
FETCH NEXT FROM @Cursor INTO @Sql
END
CLOSE @Cursor DEALLOCATE @Cursor
GO
EXEC sp_MSForEachTable 'DROP TABLE ?'
GO

Delete All Stored Procedures

declare @procName varchar(500)
declare cur cursor
for select [name] from sys.objects where type = 'p'
open cur

fetch next from cur into @procName
while @@fetch_status = 0
begin
if @procName <> 'DeleteAllProcedures'
exec('drop procedure ' + @procName)
fetch next from cur into @procName
end

close cur
deallocate cur

 

Delete All Views

 

declare @procName varchar(500)
declare cur cursor
for select [name] from sys.objects where type = 'v'
open cur

fetch next from cur into @procName
while @@fetch_status = 0
begin
exec('drop view ' + @procName)
fetch next from cur into @procName
end
close cur
deallocate cur

 

Delete All Functions

 

declare @procName varchar(500)
declare cur cursor
for select [name] from sys.objects where type = 'fn'
open cur

fetch next from cur into @procName
while @@fetch_status = 0
begin
exec('drop function ' + @procName)
fetch next from cur into @procName
end

close cur
deallocate cur
A Lap around WebMatrix – Vancouver on August 24th.

 

I just checked and it looks like the folks at .NET BC have managed to get around to post my up-coming presentation. 

Capture

Topic: A Lap around WebMatrix
Please join Rob Chartier, VP of Engineering & Support at DotNetNuke, in a brief Lap around the new WebMatrix tool from Microsoft. Rob will cover most of the high-level features of the tool and even dig into the new Razor syntax.

http://netbc.ca/DNCal/EventDetail.aspx?date=2010/08/24

webx-hero

 

See you then!

More on Dynamic Language Execution within DotNetNuke

A few weeks ago I ripped out a module over the weekend which allowed a Content Editor for DotNetNuke to be able to actually start scripting content within the UI.  Imagine being able to embed scripts within (a) the Text/Html module which is complied+interpreted on the server; a Text/Html/Script module.

That is essentially what this Dynamo module allows you to do; Dynamic Language Execution within DotNetNuke.  It doesn’t use Reflection.Emit so it is safe in Medium Trust.

I wanted to do a follow-up post to highlight some of the changes that I have made over the past few weeks and to request feedback from you folks.

Context Switching

The first revision of my module did not allow you to switch between HTML and Script in a single script block.  In fact it took the entire input you gave it and treated it as Script.  Thus you had to hard code all HTML blocks within “echo” statements (aka Response.Write).  This was one of my goals for the first release, but I decided to move ahead without it. 

I spent a decent amount of time figuring out the best way to handle this, and here is what I came up with:

  1. By Default the script will treated as HTML. 
  2. You must enclose actual Script within @{  …..  }@ tags.
  3. It will process each Context in order and append that to a string builder
  4. Finally, once all Context blocks are complete, emit a LiteralControl with the final content.

I have this working in the recent builds (past 1.5.0), and working quite well.

Capture 

Error Handling

There are two core areas around Error Handling that I had defaulted to (poorly) in the past.  The first was when the Jint (the internal mechanism that handles the Dynamic Scripting Support) throws/returns an error I added it to the module output and emitted it to the page along with the rest of the content.  This is now being suppressed.  I also break out of step execution of all of the context switching.  That is, the step which threw the exception will be the last one to execute.  This is for a normal user.  For a SuperUser it will Append() the exception and continue the execution.

Second, I set Jint’s debug mode to that of the HttpContext.Current.IsDebuggingEnabled flag.  So it aligns Jint’s debugging with what you have set in web.config.

Security

The last piece that I still have left to take care of is Security.  Ultimately the Jint engine relies on two methods to handle security.  The first of which is to completely Disable the security and the second is to utilize the System.Security.Permissions Namespace in order to control access.  For this release I have just completely Disabled Security.  My next set of work will be dedicated to creating an Host->Scripting menu item which allows you to control Security on a per Portal basis.

 

Finally, if you are using the module for anything or if you have any feature enhancements or changes, please let me know.  I plan on contributing to this module for the coming months.

I just updated to 1.6 on Codeplex.  Go upgrade now!

Sprite and Image Optimization Framework & DotNetNuke

Introduction

The folks over at Microsoft recently pushed a open source release of their Sprite and Image Optimization Framework onto Codeplex last week.  And after a few tweaks I was able to get it running within DotNetNuke, here is how…

Download the Sprite and Image Optimization Framework.  Unzip it and open up the ImageOptimizationFramework.sln file using Visual Studio .NET 2010. 

Getting it 3.5 Compatible

If you are still running your DotNetNuke installation on 3.5, you will need to change the “Target Framework” for both the “Web Forms Control” and the “Image Optimization Framework” down to 3.5.  This can be achieved by right clicking the project and under the “Application” Tab / Target Framework choose “.NET 3.5 Framework”, save and close both property windows.

Next you will notice that when you attempt to build (now that we are on 3.5) you will get a compiler error.  In ImageOptimization.cs I changed the following method to look like:

private static void RebuildFromCacheHit(string key, object value, CacheItemRemovedReason reason) {

  var data = (object[])value;
  string path = (string)data[0];
  IEnumerable<string> cachedDirectoriesBelowCurrentFolder = (IEnumerable<string>)data[1];

That is, I replaced their use of the Tuple class with the generic object[]

The second method that needed to be changed is:

private static void InsertItemIntoCache(string path, IEnumerable<string> directoriesBelowCurrentFolder) {
  string key = Guid.NewGuid().ToString();
  //var value = Tuple.Create(path, directoriesBelowCurrentFolder);
  var value= new object[]{path, directoriesBelowCurrentFolder};
  HttpRuntime.Cache.Insert(key, value, new CacheDependency(path), Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, RebuildFromCacheHit);
}

Notice again, it was converting the Tuple to use an object[].  I’m sure there is a more optimal way available but this is good enough for this round of testing.

The solution should compile now. 

DotNetNuke

If you navigate to the folder”  %My Download Directory%\sprite-image-optimization-framework\WebFormsControlSample\Bin\   you will see the 2 compiled DLLs and PDB files. XCopy deploy these into your local (testing) DNN installation’s bin folder.

You will now need to crack open your web.config for your DNN installation and add the following line, under the “System.Web/httpModules” section:

<add type ="Microsoft.Samples.Web.ImageOptimizationModule" name ="Microsoft.Samples.Web.ImageOptimizationModule"/>

This HttpModule assumes that there is a folder at the root of your web site named App_Sprites.  You should create that folder now otherwise you will get a yellow screen of death at first load.

The HttpHandler wires up a cache dependency to the App_Sprites folder after “indexing” the content.  It will take all of the images in that folder and create the Sprite Image, and associated CSS files.  I also noticed that it will actually rebuild these files if they are deleted for any reason.

Capture

Notice the CSS files, a dat file and the new sprite0.png file; all of these were created based on the existing images in that folder by the HttpHandler.

Within your module folder structure, create a “App_Sprites” folder, copy your images in to that folder.  Like so:

image

Notice that I set references to both of the ImageOptimizationFramework.dll and the ImageSprite.dll in this project.

In your code-behind file for your module, we will follow the same pattern as the HttpHandler in order to add our Cache Dependency to the ImageOptimizer, like so:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.Samples.Web;

namespace DNN.Sprites.DesktopModules.SpriteSample
{
    public partial class Sprite : DotNetNuke.Entities.Modules.PortalModuleBase
    {
        private static readonly object _lockObj = new object();
        private static bool _hasAlreadyRun;

        static Sprite()
        {
            lock (_lockObj)
            {
                if (_hasAlreadyRun)
                    return;
                else
                    _hasAlreadyRun = true;
            }

            ImageOptimizations.AddCacheDependencies(System.Web.HttpContext.Current.Server.MapPath("~/DesktopModules/SpriteSample/App_Sprites/"), rebuildImages: true);
            return;
        }

        protected void Page_Load(object sender, EventArgs e)
        {

        }
    }
}

 

And finally in our ascx document we can now use the new ImageSprite control to refer to our images:

 

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Sprite.ascx.cs" Inherits="DNN.Sprites.DesktopModules.SpriteSample.Sprite" %>
<%@ Register TagPrefix="asp" Namespace="Microsoft.Samples.Web" Assembly="ImageSprite" %>
<asp:ImageSprite runat="server" ImageUrl="~/DesktopModules/SpriteSample/App_Sprites/windowsLogo.png" />
<asp:ImageSprite ID="ImageSprite1" runat="server" ImageUrl="~/DesktopModules/SpriteSample/App_Sprites/xbox.png" />
<asp:ImageSprite ID="ImageSprite2" runat="server" ImageUrl="~/DesktopModules/SpriteSample/App_Sprites/office.png" />

 

Which emits:

Capture1

With the HTML:

 

<div id="dnn_ctr6123_ModuleContent" class="SpriteContent">
    <img class="windowsLogo-png" src="data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" style="border-width:0px;" />
    <img id="dnn_ctr6123_Sprite_ImageSprite1" class="xbox-png" src="data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" style="border-width:0px;" />
    <img id="dnn_ctr6123_Sprite_ImageSprite2" class="office-png" src="data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" style="border-width:0px;" />
</div

Play close attention to the class attribute as well.  They are using a fairly simplistic naming convention to automatically emit the attribute for predictability.

Although the project seems to be in the early stages I can see it receiving very broad adoption in the near future.

More Posts