by community-syndication | Sep 10, 2009 | BizTalk Community Blogs via Syndication
[Source: http://geekswithblogs.net/EltonStoneman]
Keeping up the fluent work, I’ve put together a fluent interface which wraps the framework HtmlTextWriter. For ASP.NET MVC, this makes generating HTML in extension methods to HtmlHelper safer than string.Format() and more readable than HtmlTextWriter:
public static string Image(this HtmlHelper helper, string imageRelativeUrl, string altText)
{
return FluentHtmlTextWriter.Begin()
.WriteTag(HtmlTextWriterTag.Img)
.WithAttribute(HtmlTextWriterAttribute.Src, GetImageUrl(imageRelativeUrl))
.WithAttribute(HtmlTextWriterAttribute.Alt, altText)
.End();
}
The equivalent using HtmlTextWriter is:
public static string Image(this HtmlHelper helper, string imageRelativeUrl, string altText)
{
StringBuilder htmlBuilder = new StringBuilder();
HtmlTextWriter writer = new HtmlTextWriter(new StringWriter(htmlBuilder));
writer.AddAttribute(HtmlTextWriterAttribute.Src, GetImageUrl(imageRelativeUrl));
writer.AddAttribute(HtmlTextWriterAttribute.Alt, altText);
writer.RenderBeginTag(HtmlTextWriterTag.Img);
writer.RenderEndTag();
writer.Flush();
return htmlBuilder.ToString();
}
Unlike the framework writer, you’re not constrained to specify attributes in any particular order, and tags which aren’t nested can be written with a single WriteTag(), rather than BeginTag() and EndTag() calls. The writer copes with multi-level tag hierarchies – this sample builds a Superfish CSS menu:
FluentHtmlTextWriter writer = FluentHtmlTextWriter.Begin();
writer.BeginTag(HtmlTextWriterTag.Ul)
.WithAttribute(HtmlTextWriterAttribute.Id, “menu.Name”)
.WithAttribute(HtmlTextWriterAttribute.Class, “sf-menu sf-vertical”);
.BeginTag(HtmlTextWriterTag.Li)
.BeginTag(HtmlTextWriterTag.A)
.WithAttribute(HtmlTextWriterAttribute.Class, “sf-with-ul”)
.WithAttribute(HtmlTextWriterAttribute.Href, “#”)
.WithValue(“Link 1”)
.WriteTag(HtmlTextWriterTag.Span)
.WithAttribute(HtmlTextWriterAttribute.Class, “sf-sub-indicator”)
.WithValue(“»”)
.EndTag()
.EndTag()
.EndTag();
string html = writer.End();
Assert.AreEqual(“<ul id=\”menu.Name\” class=\”sf-menu sf-vertical\”>\r\n\t<li><a class=\”sf-with-ul\” href=\”#\”>Link 1<span class=\”sf-sub-indicator\”>»</span></a></li>\r\n</ul>”,
html);
The HtmlTextWriter equivalent is unthinkable.
Patrik H%u00e4gne has an alternative fluent HtmlTextWriter implementation, which is nicely put together, but I wanted slightly different functionality. Firstly I wanted to get the HTML string from the writer directly, without needing to instantiate a StringBuilder and StringWriter. Secondly I wanted minimal new code – Patrik uses a separate class to manage writing attributes, and has specific functions for known tag types. Thirdly, I didn’t really like Patrik’s syntax, with the need to specify the tag type when you write an end tag – and when tags aren’t nested, I wanted to write them in a single unit:
string html = FluentHtmlTextWriter.Begin()
.WriteTag(HtmlTextWriterTag.Span)
.WithAttribute(HtmlTextWriterAttribute.Id, “id_span”)
.WithValue(“contents_span”)
.End();
Assert.AreEqual(“<span id=\”id_span\”>contents_span</span>”, html);
My version is on MSDN Code Gallery here: FluentHtmlTextWriter. It works by building up a list of actions when you start writing a tag, and flushing them in the correct order to an internal HtmlTextWriter when you start writing the next tag. When you call End() it flushes the internal writer and outputs its contents. An alternative constructor lets you write directly to an output stream, in which case you can Flush() the writer and don’t need to call End().
The current implementation only deals with basic tag, attribute and style functionality, and doesn’t include optional HTML encoding overloads. It’s only 75 lines of code, and extending it should be trivial.
There is a negligible performance hit in using FluentHtmlTextWriter – running the image tag generation code above 20,000 times on my dev machine, the fluent version takes between 0.01and 0.02 seconds longer than the framework version (on average 0.07 seconds compared to 0.05).
by community-syndication | Sep 10, 2009 | BizTalk Community Blogs via Syndication
Last night we had an exam cram, where keen and interested delegates bunkered down
and got their neurons firing.
I went through this exam with them giving them tips and sharing my general SharePoint
knowledge around this.
Today – the good news was that I passed three delegates whom took the exam *today*
and all passed!!! Well done guys!
Here’s the ppt deck that I used – enjoy and well done all!
by community-syndication | Sep 10, 2009 | BizTalk Community Blogs via Syndication
We’re in the thick of TechEd 2009 here in Australia on the Gold Coast (tough place
to have a conference 😉 Sun, sand and a beach that stretches for miles 1 block away)
Big thanks to those of you that attended my session – great turn out and all my demos
worked like a charmthat doesn’t happen every day 🙂
Here’s the powerpoints and demo files:
PowerPoints –
by community-syndication | Sep 9, 2009 | BizTalk Community Blogs via Syndication
I just got the HL7 DASM pipeline working with two custom Decode pipeline components (String Replace and Archive).
I was receiving batched messages, and if there was an error in any of the trigger messages, the entire batch was being rejected with no discernable error message other than the context property: ParseError=True (wow, I can really troubleshoot with that indicator)
So I was given hotfix KB 973910 and started testing it. I did not seem to fix the problem.
I changed and used the out of the box HL7 DASM, and it started working (debatching the file and suspending only the trigger message that was actually in error). I decided to rebuild the custom pipeline, I removed the HL7 DASM pipeline component from the .btp file, removed the HL7 DASM from the tool box, and the re-added the pipeline to the tool box and then added it to the .btp file. I then deployed it and ran a file through successfully.
Here is the wives’ tale: If you have a custom HL7 pipeline component, you need to remove the HL7 DASM completely from Visual Studio and then re-add it so that BizTalk will see the new behavior.
Please let me know if this is a fallacy, and what the minimum amount of work that I have to do to have BizTalk see a newly hotfixed pipeline component.
by community-syndication | Sep 8, 2009 | BizTalk Community Blogs via Syndication
I have been using ANTS Profiler to conduct some profiling against some WCF services hosted on Windows 2008 that I have been working on. This was working pretty well with services hosted in IIS, but I was experiencing some difficulties when attempting to hook it all up with WCF services hosted in WAS using the net.tcp binding. I still don’t have a definitive answer as to why I have been experiencing issues, but I have a workaround procedure in order to get it working.
Firstly, you need to create a profile and choose the Windows service application type to profile, selected WAS from the, as shown in the following screen capture.
Once you click the Start Profiling button the WAS service should be stopped and started. It is at this point where I experience my first problem, as it seems to hang at the starting state. Note the status bar in the following screen capture.
Now it appears that the service never starts and this state is also shown when you browse the Windows Process Activation Service service in the Services snap-in. After a bit of playing around I managed to get past this issue, by following these simple steps:
1. Execute iisreset from a command prompt window
2. Once iisreset has restarted, browse to an HTTP WCF endpoint on the server
3. The profiler should now be started
Now, at this point I also experienced an issue when attempting to take a memory snapshot, receiving the following error message where <some folder> is the location where it is trying to save the data.
Could not start profiling as the processing being profiled was unable to create the file ‘<some folder>’.You can set the RGTEMP or the RGIISTEMP environment variables in the System control panel to override the location used for profiler results files.
In order to get around this I simply gave everyone permissions to the folder it was trying to save to. I am sure there was a more focused way that this could be achieved, but as this was a development machine I was quite happy with this.
by community-syndication | Sep 8, 2009 | BizTalk Community Blogs via Syndication
I am busy creating a BizTalk Software factory for BizTalk 2009. So instead of going through all kinds of repeatable steps, enter data, do some more stuff, add pesky references do more stuff, add a map, add another map, add an orchestration, Start from…(read more)
by community-syndication | Sep 8, 2009 | BizTalk Community Blogs via Syndication
If you spend some time using
Fluent NHibernate, you’ll want to use its neat style of mapping for all data access, even when you’re working against traditional DALs. I’ve put a sample up on MSDN Code Gallery for this scenario, using a fluent style of mapping between domain objects and data readers populated by stored procedure calls.
The interface is very similar to FNH, with a mapping class used for each domain entity – this is a simple mapping class:
public class PostCodeMap : DataReaderMap<PostCode>
{
public PostCodeMap()
{
Map(x => x.InwardCode, “PS_IN”);
Map(x => x.OutwardCode, “PS_OUT”);
}
}
The string constants define the column names expected in the data reader, and the base class takes care of running the map. For more complex entities, DataReaderMap also includes mapping via a conversion function:
Map<string, bool>(x => x.Activated, “AccountActivated”, Legacy.FromBoolean);
– where the mapping specifies to and from types, and a delegate to invoke for the conversion (in this case, a method which converts a legacy string representation of a boolean – Y/N – to a bool).
For composite objects, the base map includes referencing, for cases where the child entity is loaded from the same data reader as the parent entity:
References(x => x.Address, new AddressMap());
Where the child entity is read from a separate data reader, then the composition needs to be done outside of the map in a repository or an assembler component. The Load class isolates calling the stored procedure, so you get a fluent interface for populating domain objects, and collections of objects:
public User GetUser(Guid userId)
{
//populate basic details:
User user = Fluently.Load<User>().With<UserMap>()
.From<GetUser>(i => i.UserId = userId,
x => x.Execute());
//add accounts:
user.Accounts = Fluently.Load<List<Account>>().With<AccountMap>()
.From<GetUserAccounts>(i => i.UserId = userId,
x => x.Execute());
return user;
}
The From() call specifies the type of stored procedure, an action to populate the object, in this case setting up the UserId parameter, and a function to call which returns a data reader, in this case Execute().
The full sample is on the gallery here: Fluent DAL Mapping . It’s a simple task to extend the sample to load datasets, or to populate update procedure calls from entities. If your database is sufficiently conventional this could be extended to provide FNH-style auto-mapping, reflecting over entities and using conventions to map properties to column names.
by community-syndication | Sep 8, 2009 | BizTalk Community Blogs via Syndication
by community-syndication | Sep 7, 2009 | BizTalk Community Blogs via Syndication
Instead of scanning the Event Log and capturing when the Receive Locations or Send Ports go down, you can use the following triggers to send out an email when they change status:
Receive Location:
CREATE TRIGGER [dbo].[ReceiveLocationChangeNotification]
ON [dbo].[adm_ReceiveLocation]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @oldstatus int
DECLARE @newstatus int
DECLARE @ReceiveLocationName nvarchar(256)
DECLARE @status nvarchar(10)
DECLARE @message nvarchar(300)
--Was the status not changed
IF NOT UPDATE([Disabled])
BEGIN
RETURN
END
--Otherwise send out email
select @oldstatus=(select [Disabled] from Deleted)
select @newstatus=(select [Disabled] from Inserted)
select @ReceiveLocationName=(select [Name] from Inserted)
SET @message=@ReceiveLocationName+' recieve location changed from '+ case
when @oldstatus=-1 then 'Disabled'
when @oldstatus=0 then 'Enabled'
END + ' to ' +
case
when @newstatus=-1 then 'Disabled'
when @newstatus=0 then 'Enabled'
END
EXEC msdb.dbo.sp_send_dbmail @recipients='[email protected]',
@subject = @message,
@body = @message,
@body_format = 'HTML' ;
-- print @message
END
GO
Send Port:
CREATE TRIGGER dbo.SendPortChangeNotification
ON dbo.bts_sendport
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @oldstatus int
DECLARE @newstatus int
DECLARE @PortName nvarchar(256)
DECLARE @status nvarchar(10)
DECLARE @message nvarchar(300)
--Was the status not changed
IF NOT UPDATE(nPortStatus)
BEGIN
RETURN
END
--Otherwise send out email
select @oldstatus=(select nPortStatus from Deleted)
select @newstatus=(select nPortStatus from Inserted)
select @PortName=(select nvcName from Inserted)
SET @message=@PortName+' changed from '+ case
when @oldstatus=1 then 'Unenlisted'
when @oldstatus=2 then 'Stopped'
when @oldstatus=3 then 'Started'
END + ' to ' +
case
when @newstatus=1 then 'Unenlisted'
when @newstatus=2 then 'Stopped'
when @newstatus=3 then 'Started'
END
EXEC msdb.dbo.sp_send_dbmail @recipients='[email protected]',
@subject = @message,
@body = @message,
@body_format = 'HTML' ;
--print @message
END
GO
(Did I mention the disclaimer noted on the right side of this blog?)
by community-syndication | Sep 7, 2009 | BizTalk Community Blogs via Syndication