Microsoft Gold Certified Partner

Archive for the ‘Techy stuff’ Category

Asynchronous ASP.NET MVC and SqlDependency

Tuesday, July 12th, 2011

This is a quick example showing how to set up Asynchronous Actions in ASP.NET MVC and SQLDependency using a standard example – Chat application.

1. IIS Threading

IIS 7 creates a new thread from the thread pool whenever it receives a request from the client. When the thread processes the request synchronously it cannot handle other requests since it’s waiting for operation completion. This can be a problem for applications with a big number of requests and long running IO operations. (this is a very simplified version, lots more is happening in IIS but let’s not worry about this…).
When the thread pool no longer has any available threads on the server the requests will start being queued in the global IIS queue. Once the queue reaches its limit IIS will start returning “Server Busy” AKA 503.

503 error

This error is often generated when we are performing long running synchronous tasks or spamming the server with requests when it’s not really needed. A good / classic example of an application that can do both is the chat application.

When created incorrectly you can use JavaScript setInterval/setTimeout to get data from the server every X ms/s regardless of the changes (pooling).This will cause a big load on the server for every client / browser tab open.

There are several solutions for this problem. One of them is to use a long pooling technique:

2. Asynchronous request to the rescue

When an asynchronous request is executed on the CLR Thread Pool instead of waiting  for the process to finish, the thread can go back to the thread pool and serve other request. Once the processing is finished a new thread (or the same…) is dispatched to process the remainder of the request and render the results. This increases performance for long running operations since threads can be used in a more efficient way.

I’ll use SqlDependency to get notifications whenever someone submits a chat message and asynchronous MVC actions to keep requests open and update the Chat window only when needed.

3. SqlDependency configuration

SqlDependency allows registering for query notifications in SQL server. This allows us to be notified on the changes in the thunderlying database instead of querying it for changes.

  • Enable CLR integration

EXEC sp_configure 'clr enabled', 1

go

RECONFIGURE
  • Enable SQL Service Broker

ALTER DATABASE <DataBaseNameHere> SET ENABLE_BROKER
  • Setup user permissions

GRANT CREATE PROCEDURE TO <UserNameHere>;

GRANT CREATE SERVICE TO <UserNameHere>;

GRANT CREATE QUEUE TO <UserNameHere>;

GRANT REFERENCES ON CONTRACT::[http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification] TO <UserNameHere>;

GRANT SUBSCRIBE QUERY NOTIFICATIONS TO <UserNameHere>;

GRANT CONTROL ON SCHEMA::[dbo] TO <UserNameHere>;

GRANT IMPERSONATE ON USER::DBO TO <UserNameHere>;

4. “Coding” SqlDependency

Implementing SqlDependency is fairly simple but has a few quirks. To get the SqlDependency working you just need to:

  • Call SqlDependency.Start method which will start listening for notifications.
  • Create and Open new SqlConnection
  • Create SQL command that you want to “listen to”. In my example I’m listening for changes in all chat messages in a room specified by constant “ROOM_NUMBER”.
  • Create new SqlDependency object that takes SqlCommand as a parameter and handle OnChange event. This event will fire whenever there is a change that affects the results of our query.
  • Execute Query

Unfortunately LINQ to SQL or Entity Framework does not work with SqlDepenency. That means there is no way to create a new EF ObjectContext, create a LINQ query and use it as SQL notification subscription. There is no way…or I just didn’t find a way, that is. If anyone knows how to do it please let me know! (I’ve tried


System.Runtime.Remoting.Messaging.CallContext.SetData("MS.SqlDependency", dependency.Id);

but couldn’t make it work…)

Keep in mind that when working with SqlDependency:

5. Simple chat application

To create Asynchronous actions in MVC we need to:

  • Make the controller inherit from AsyncController
  • Action method needs to be divided into 2 methods:

<MethodName>Async ( this method needs to return void ),

<MethodName>Completed (this method returns actual ActionResult )

  • AsyncManager contains several properties/methods that are required to create asynchronous action:
    • Increment / Decrement – these 2 methods exposed by OutstandingOperations property are used to indicate the start and end of long running tasks to AsyncManager.
    • Parameters dictionary is used to store results of running tasks. Every key from this dictionary will be passed as parameter to <MethodName>Completed action.

There are also 2 interesting attributes that will help us in creating Async actions:

       AsyncTimeout

and

       NoAsyncTimeout

Names of these Action Filter attributes should be self-explanatory. By default async method will time-out after 45 seconds. In that case we can either write the code to re-request an asynchronous method or set it disable timeout. In this example I’ll go with setting timeout to 90 seconds so we can see what’s actually happens.

Sample code controller code (I hope that the code comments and the explanation above should make this clear):


public class ChatController : AsyncController {

      [AsyncTimeout(90000)]
      public void GetMessagesAsync(){
             AsyncManager.OutstandingOperations.Increment();
             SqlConnection conn = null;
             try
             {
                  string connString = ConfigurationManager.ConnectionStrings["ChatConnectionString"].ConnectionString;
                  conn = new SqlConnection(connString);
                  conn.Open();    // open new connection and create command to notify about all new Chat-Messages in -ROOM_NUMBER- const
                  using (var sqlCommand = new SqlCommand(@"SELECT dbo.Chat.Id FROM dbo.Chat WHERE dbo.Chat.RoomNumber = @room", conn))
                  {
                        sqlCommand.Parameters.AddWithValue("room", Configuration.ROOM_NUMBER);
                        var sqlDependency = new SqlDependency(sqlCommand);
                        //handle onChange event - this will be fired whenever there is a change in database that affacts our query
                        sqlDependency.OnChange += (sender, e) =>
                        {
                            //change detected - get all messages...
                            Models.MyValetBayEntities entities = null;
                            try
                            {
                                  entities = new Models.MyValetBayEntities();
                                  var query = from c in entities.ChatRoom
                                  where c.RoomNumber == Configuration.ROOM_NUMBER
                                  select c;
                                  AsyncManager.Parameters["chatModel"] = query.ToArray();
                            }
                            finally
                            {
                                  entities.Dispose();
                                  //...and complete async operation
                                  AsyncManager.OutstandingOperations.Decrement();
                            }
                        };
                   //execute query with associated SqlDependency to subscribe for notifications
                   sqlCommand.ExecuteNonQuery();
                 }
           }
           catch {
               //make sure that if something goes wrong we are still have proper AsyncManager operations count
               AsyncManager.OutstandingOperations.Decrement();
           }
           finally
           {
               if (conn != null)
               {
                   conn.Dispose();
               }
           }
       }
       public ActionResult GetMessagesCompleted(Models.Chat[] chatModel){

              return PartialView("Chat", chatModel);
       }
}

Sample Javascript:


$.ajaxSetup({
      // Disable caching of AJAX responses
      cache: false
});

function getNews(){
         $.ajax({
           url: '@Url.Action("GetMessages", "Chat")',
           success: function (data) {
                    //update messages ...
                    $('div#content').html(data);
                    //... and subscribe for notification again
                    getNews();
           },
           error: function () {
                  getNews(); //timeout error create new request
           }
         });
}

getNews();

Part of Global.asax

protected void Application_Start(){
      //... MVC registration removed for simplicity
      SqlDependency.Start(connString);
}

private void Application_End(){
      SqlDependency.Stop(connString);
}

DEMO (off-line)

An asynchronous request waiting for information from the server in action:

IE Pending

Chrome Pending

6. The End…

I hope you enjoyed my post. This demo could be probably improved by using HTML5 WebSockets but that’s something for another blog post since WebSockets are not supported that well yet…

Please also note that creating asynchronous methods will be simplified with C# 5 with async and await keyword. Have a look at http://msdn.microsoft.com/en-us/vstudio/gg316360 for more details but please be careful with installing it since it’s only CTP (at the time of writing this blog post).

Dynamic Panorama Control (WP7 basics)

Monday, December 13th, 2010

In almost every Windows Phone 7 commercial we can see Panorama control.
*
Panorama (and also Pivot) control is a way of navigating in Windows Phone 7 applications. It allows us to use big, horizontal canvas that extends beyond right and left side of the screen.
Most examples that I found shows how to create “static” panorama control – control with already defined number of “PanoramaItems”.
I think that dynamic panoramas can be used for more flexible applications when user can define on his own, how many “pages” should application display and what content should be displayed.
I’ll quickly show how to create dynamic BBC reader application where user can select list of channels that he finds interesting and define how applications panorama control should look like.
Note: I didn’t spent too much time on polishing this application. Goal of this app is just to show how to create dynamic panorama controls.

1. Main Page XAML:
Here we are simply creating a List of checkboxes and an empty Panorama control.

    <Grid x:Name="LayoutRoot" Background="Transparent"  Margin="0,0,0,0">
        <ListBox Name="channelSelection"  SelectionMode="Multiple"
                 ItemsSource="{Binding ChannelSelection}" Margin="0,0,0,96">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <CheckBox x:Name="McCheckBox"
                      Canvas.Left="10" Canvas.Top="10"
                      Content="{Binding Name}"
                      IsChecked="{Binding Checked, Mode=TwoWay}">
                    </CheckBox>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <Button Name="channelSelected" Content="Save changes"
                Width="230" Margin="125,355,125,0" Height="90" VerticalAlignment="Bottom">
        </Button>

        <!--Panorama control-->
        <controls:Panorama Title="BBC News" Name="panorama" Visibility="Collapsed">
        </controls:Panorama>
    </Grid>

2. Handling Channel selection (Save button click)
After user selects channels, I’m hiding “channel selection”.
For each selected channel I’m adding new custom control to panorama items collection
and displaying it. BBCChannel constructor is taking channel object and panorama index as a parameter – latter one just to load only visible item.

        ///
        /// Handles 'save changes' button click (channel selection)
        ///
        void channelSelected_Click(object sender, RoutedEventArgs e)
        {
            panorama.Visibility = System.Windows.Visibility.Visible;
            channelSelection.Visibility = System.Windows.Visibility.Collapsed;
            channelSelected.Visibility = System.Windows.Visibility.Collapsed;

            var selectedChannels = (channelSelection.ItemsSource as ObservableCollection).Where(chan =&gt; chan.Checked == true).ToList();

            for (var index = 0; index &lt; selectedChannels.Count ;index++ )
            {
                BBCChannel chan = new BBCChannel(selectedChannels[index], index);
                panorama.Items.Add(chan);
            }
        }

3. Handling panorama “Selection Changed” event:
This will force BBCChannel control to load content when user tries to move to the next panorama item control.

            panorama.SelectionChanged += new EventHandler(panorama_SelectionChanged);
        ///
        /// Handles panorama item changed
        ///
        void panorama_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            (e.AddedItems[0] as BBCChannel).LoadComponent();
        }

4. BBCChannel user control XAML

    <Grid>
        <ProgressBar Name="progress" IsIndeterminate="True" Height="40" Style="{StaticResource PerformanceProgressBar}"></ProgressBar>
        <controls:PanoramaItem Name="panoNewsItem" Header="{Binding Name}" >
            <Grid>
                <ListBox ItemsSource="{Binding Items}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                            <StackPanel Orientation="Horizontal" Margin="0,0,0,17">
                                <Image Height="49" Width="66" Source="{Binding ImageSource}">
                                </Image>
                                <StackPanel Width="311">
                                    <TextBlock Text="{Binding Title}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                                    <TextBlock Text="{Binding Description}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
                                </StackPanel>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
            </Grid>
        </controls:PanoramaItem>
    </Grid>

5. Data source contains list of “Channel” objects:

            this.ChannelSelection.Add(new Channel() { Name = "Top Stories", RssURL = "http://feeds.bbci.co.uk/news/rss.xml" });
            this.ChannelSelection.Add(new Channel() { Name = "World", RssURL = "http://feeds.bbci.co.uk/news/world/rss.xml" });
            this.ChannelSelection.Add(new Channel() { Name = "Business", RssURL = "http://feeds.bbci.co.uk/news/business/rss.xml" });
            this.ChannelSelection.Add(new Channel() { Name = "Politics", RssURL = "http://feeds.bbci.co.uk/news/politics/rss.xml" });
            this.ChannelSelection.Add(new Channel() { Name = "Health", RssURL = "http://feeds.bbci.co.uk/news/health/rss.xml" });
            this.ChannelSelection.Add(new Channel() { Name = "Entertainment &amp; Arts", RssURL = "http://feeds.bbci.co.uk/news/entertainment_and_arts/rss.xml" });
            this.ChannelSelection.Add(new Channel() { Name = "Science/Nature", RssURL = "http://feeds.bbci.co.uk/news/science_and_environment/rss.xml" });
            this.ChannelSelection.Add(new Channel() { Name = "Technology", RssURL = "http://feeds.bbci.co.uk/news/technology/rss.xml" });
            this.ChannelSelection.Add(new Channel() { Name = "Education", RssURL = "http://feeds.bbci.co.uk/news/education/rss.xml" });

Each channel object contains list of NewsItem objects; those object are responsible for storing News title, description, image URL and link to main article.

6. Final Result:

Dynamic Panorama (links to youtube)

This is very basic tutorial but I hope it will help someone.

* Image from MSDN Library

Using SharePoint 2010 in education

Thursday, November 25th, 2010

We have recently been working on SharePoint installations in educational establishments, but it seems very few are  making good use of SharePoint’s functionality and feature sets. SharePoint has a number of valuable applications in educational settings:

  • Document Management: The first is as a policy / document management tool. SharePoint’s origins are in document management and approval; this allows you to control the editing and approval of school policy from creation right through to publishing.
  • Virtual Learning Environment: With the ability to quickly and easily create sites and workgroups plus a number of plug-ins to enable virtual learning. SharePoint is a natural home for an integrated virtual learning environment.
  • E-Learning including:
    Teacher Programmes
    Student e-Learning Programs
    Managing e-learning content
  • SharePoint also has an open source plug in called SCORM which is a framework for e-Learning which allows you to have course development by external companies and is easily deployed within SharePoint.
  • Teaching Resources: An easy to navigate and search content base can be created to safely and securely store teaching resources. This helps to spread best practice and innovation within the establishment.
  • Student and Staff Profile Management: Through the use of MySite Students and teachers can create their own personal portal managing their work and information, all safely and securely stored.
  • Student/Teacher Performance Monitoring: Through the use of custom forms and workflows you can create safe and secure review programs that allow you to raise alerts in the case performance challenges.
  • Parents Participating Sessions: Parents can be given restricted access to an area of the site to collaborate on events or projects.
  • Policies, Documents and Record management: Document stores are second nature to SharePoint so workflow managed policies and other documents are an easy quick win.
    Publishing: With Content Management both externally and internally you can run both your website and intranets through it.
  • Admissions/Recruitment management: Workflow comes into its own again when you are dealing with admissions and recruitment; with a full audit history you can track all admissions and automatically archive.

This is not an exhaustive list of  uses for SharePoint within schools and colleges, but just a selection which we have worked on so far.

TFS to TFS Migration between two domains

Wednesday, November 17th, 2010

Here is an article describing the migration of projects between TFSs in two different domains. Using the TFS Integration tool, this article provides the configurations required to acheive the desired integration results.

The scenario is projects TFS 2008 in “DomainA” need to be migrated with TFS 2008 in “DomainB”. Obviously we would require that all the version history and user information to be retained along with the work items.
Unfortunately the current version of the TFS Integration Tool (Aug 2010) does not support retaining the original time stamp of the change sets, though the comments are retained. We need to find work arounds using source code modifications. Some recommendations are given here

http://social.msdn.microsoft.com/Forums/en/tfsintegration/thread/f9e0fbe5-2700-401a-bd02-de71926502cc

http://social.msdn.microsoft.com/Forums/en-GB/tfsintegration/thread/43bae5cc-5554-4e38-94ae-9efa8c8bd110

TFS Integration Tool facilitates to add the corresponding mappings, before we start the integration. At the end we will see that elements in the Target are associated with the users in the DomainB

First when you run the TFS Integration tool on source which is in DomainA, and with DomainA\Administrator account (Migration Service Acccount), Perform the following steps

1. Select the “TFS to TFS Version Control and Work Item Tracking..” template to create a configuration in the TFS Integration tool. Select custom workflow type and set the SyncContext=”Disabled”. Enabling SyncContext will check for the meta data of User Groups, Global Lists and WI Definitions on source and target. We should disable it. You should consider additional configuration if there are custom WI definitions on the source.

2. EnableBypassRuleDataSubmission – setting this value to ‘true’, preserves the users on the target TFS server. Setting it ‘false’ will make the migration service account will be the author of *all* the migrated changes on the target TFS server.

Enable it on all the source and targets. Click the ‘Edit XML’ button on each and replace
“<CustomSettings />” with


<CustomSettings>
  <CustomSetting SettingKey="EnableBypassRuleDataSubmission" SettingValue="true"/>
</CustomSettings>

2. Setup the migration service account on both source and target servers. Add the “DomainA\Administrator” to the “Service Accounts” group of the source TFS.
Use the TFS Administration Tool or the run the following command, you may not be able to add from the Team Explorer


tfssecurity /g+ "Service Accounts" n:Domain1\Administrator ALLOW /server:http://ADatumCorporation:8080

There is no option to store the credentials of the target TFS account to be used by the tool. You need to add the credentials locally at
Control Panel -> User Accounts -> Manage User Accounts -> Advanced (Tab) -> Manage Passwords -> Add

The same target server account should be added to the ‘Service Accounts’ group on the target server.
This could be DomainB\TFSAdministrator

3. Set default user id on all the Migration Sources


<MigrationSource ...>
  <Settings>
    <DefaultUserIdProperty UserIdPropertyName="DomainAlias" />
  </Settings>
</MigrationSource>

4. Apply the domain mappings


<UserIdentityMappings EnableValidation="false">
  <AliasMappings DirectionOfMapping="LeftToRight">
   <AliasMapping Left="*" Right="*" MappingRule="SimpleReplacement" />   </AliasMappings>
   <DomainMappings DirectionOfMapping="LeftToRight">
    <DomainMapping Left="DomainA" Right="DomainB"     MappingRule="SimpleReplacement"/>
  </DomainMappings>
</UserIdentityMappings>

That’s all. In the above scenario, the user names in both the domains are same. Hence only domain mappings are applied. If the user names are different, we can also apply the mappings for the users.

With the above configuration, you can run the migration.
For the identity DomainA\UserA, tool uses the DomainB\UserA identity on the target server. If the identity is not found, it uses the default identity.

The duration of migration for a project depends on the number of change groups in the source project. It takes several hours to migrate the Version Control with approximately 4000 change groups depending on the network speed connecting the source and the target. Need to keep patience, sometimes the tool seems to be doing nothing for long time (20 minutes) while processing particular change group, but in the background it is processing thousands of items associated with that change group.

There was one exception I faced during the migration that is associated with a SQL error 8152.
This is caused due to the lengthy source file URLs like
$/THIS_IS_A_LONG_PROJECT_NAME/FOLDER ONE NAME/BRANCHES/DEVELOPMENT/LONG_BRANCH_NAME/MODULES_FIRST_MODULENAME/…/…/…/…/…/…/…/…/…/…/FOLDERNAME_EXCEEDING_248_CHARACTERS

In such case, a conflict is raised by the tool. You can resolve it by moving the folders up in the hierarchy to shorten the names. Use TFmove command, which retains the history. More information about the issue can be found at

http://social.msdn.microsoft.com/Forums/en-US/tfsadmin/thread/033b0997-91a5-425f-a972-30722eacc0ef/

You can start the migration again after resolving the conflicts. Tool will skip the already migrated items and continue migrating other items to complete the migration.

Note: Known Limitations in terms of the TFS Integration Platform

The known limitations of TFS to TFS Migration tool, based on the new re-architected toolkit v2, include:

•Limited to migrating only Version Control items, Work Items, and the links between them. Other portions of Team Projects are not migrated by this tool, including Reports, Team Build data, and SharePoint content.
•Work Item IDs and Changeset numbers are not preserved during migration and new IDs are assigned sequentially as items are migrated. This implies that any references to these IDs will be invalid after migration; however, the links between work items and changesets will be migrated correctly, despite the ID changes.
•Timestamps on work item revisions and changesets will be updated to the time of migration. Any work item fields that store date time information will have their values correctly migrated, but the time of the revision will not be migrated. The most significant impact this has on a system is in reports that rely on a time dimension (i.e. Bug Trends, Code Churn). Because the migration typically occurs over a much shorter time span than the original operations, the time axis in such reports will effectively be compressed.

Comparison of SharePoint 2007 to 2010 Features

Thursday, November 11th, 2010

This article provides the list of enhancements in SharePoint 2010 over Microsoft Office SharePoint Server (MOSS) 2007 based on sites, communities, services, features, search content management and integration with Microsoft Office 2010

There are many enhancements in SharePoint 2010 over MOSS 2007, which include
• Ability to read and write to external applications
• Enabling the single interface to update multiple data repositories
• Tracking, tracing the web sites – Ability to understand the most commonly used features/pages
• Optimized mobile viewing experience
• Enhanced User experience, allowing the users to edit Office documents without MS Office components installed locally
• Enhanced functionalities for community activities


Feature Name / Area


MOSS 2007


Sharepoint Server 2010


My Site: People Profile & Personal Site


Photos And Presence


Status Updates


Ask Me About

 

New


Note Board

 

New


Recent Activities

 

New


Organization Browser

 

New


Add Colleagues


Social Bookmarks

 

New


Tags

 

New


Tag Clouds

 

New


Tag Profiles

 

New


My Network

 

New


Blogs


Wikis


Enterprise Wikis

 

New


Ratings

 

New


Colleague Suggestions


Keyword Suggestions

 

New

With Office 2010

Feature Name/Area

Description

SharePoint 2010

MOSS 2007

Co-author Documents and Presentations

Share ideas with other people simultaneously and see what areas of a document
have changed.

With co-authoring, work together in Microsoft Office Word 2010 and Microsoft
Office PowerPoint 2010, and see others’ changes tracked in documents hosted in
SharePoint 2010.

 

Simultaneously Edit Spreadsheets and Notebooks

Work together on content using a Web browser

Work together in Microsoft Office Excel 2010 and Microsoft Office OneNote 2010
Web applications simultaneously and see others’ changes in real time.

 

Highlight Changes in
Shared Notebooks

Enable multiple people to add to and change the same shared notebook. Author
names appear in near real time as changes are made.

Shared OneNote 2010 notebooks provide a clear trail of what other authors have
changed since the last user opened the notebook.

 

 

Broadcast Slide
Shows in PowerPoint

Share a PowerPoint presentation over the Web for remote or networked viewers.

Audiences do not need to have PowerPoint 2010 installed; they can see the
presentation
in high fidelity in a Web browser.

 

Save Documents and Presentations Directly to SharePoint

 

Automatically discover SharePoint document libraries to make saving content
easier and more intuitive.

People can save Office 2010 documents directly to the SharePoint 2010 document
library from Office Backstage view.

 

 

PowerPivot

 

PowerPivot for Excel 2010 provides streamlined integration and Web-based
analysis in SharePoint. Use data from multiple sources and manipulate large data sets
that have up to hundreds of millions of rows.

Publish and share analysis with less effort and enable others to enjoy the same
Data Slicers and fast-query capabilities, even when working in Excel Services
reports.

 

Publish and Share Information
Through Excel Services

 

Share analysis and results across the organization by publishing Excel 2010
spreadsheets to the Web or other SharePoint sites (intranet, extranet).

Use Backstage view in Excel 2010 to selectively publish selective parts of a
worksheet, hide formulas, and stage data to SharePoint 2010.

 

Use Backstage view in Excel 2010 to selectively publish parts of a worksheet to
SharePoint 2007.

 

Microsoft Office
Access Design for the Web

 

Microsoft Office Access 2010 applications developed in Design for Web mode can be designed
and edited for publishing to SharePoint, so people can share, collect, and
report on data.

Use Access 2010 to publish data, forms, logic/macros, and reports with nearly
the same look and feel in the browser as in Access 2010 on a PC.

 

 

Automate Metadata
Capture

Provide better, automated metadata capture in SharePoint to make information more
findable, perceptible, discoverable, navigable, manageable, and re-usable.

Use Word 2010 to provide better and more automated metadata capture from
Backstage view, including document information either added automatically or
typed quickly in AutoComplete fields.

 

Word 2010 provides automated metadata capture from Backstage view, including
document information added automatically.

 

Use Office
Backstage View

Seamlessly connect Office 2010 applications with SharePoint to provide workflow
integration, the ability to enter metadata, and social context.

By using Office Backstage view in Office 2010 applications, people can enter
metadata, interact with workflows, access authors’ profiles, view recent
content the author has created in SharePoint 2010, and more.

By using Office Backstage view in Office 2010 applications, people can enter
metadata and interact with workflows

 

Access SharePoint Templates

Access Office 2010 document templates stored in SharePoint more quickly and easily.

People can access document templates stored in SharePoint 2010 via the New
Document wizard in Office 2010 applications.

 

Apply PowerPoint Themes to SharePoint

Make customization of SharePoint sites more flexible by using themes used in
PowerPoint 2010 presentations.

People can apply themes to SharePoint 2010 sites by using the same themes as in
PowerPoint 2010.

 

 

Use Reusable Workflows

Support workflows to be used multiple times and provide workflow templates for later
use in SharePoint.

SharePoint Designer 2010 supports reusable workflows and workflows attached to content
types.

 

Visualize Workflow

Allow a workflow designer to see the steps in a SharePoint workflow in a visual
format.

Workflows developed as drawings and exported from Office Visio 2010 can be imported
into SharePoint Designer 2010 for modification and deployment.

 

Use Forms-Based Applications

Forms-based applications connect with back-end data and include workflow, reporting,
custom Web pages, and other components.

Integrate InfoPath 2010 forms with back-end data by using external lists in SharePoint
2010, and include custom sandboxed solution code.

 

Provide the Office Ribbon for InfoPath Forms Web Services

 

Provide the Fluent Office Ribbon interface for Web-enabled forms so people can easily
find, access, and use the features they want when designing Web-enabled forms.

When used with SharePoint 2010, InfoPath Forms Services provides Web-enabled forms
with their commands in a Ribbon interface.

 

View and Edit Documents, Spreadsheets, Presentations, and Notebooks in the Browser

Allow editing, even if applications are not loaded on a PC.

View and make light edits to documents through Office Web applications in a
browser. Document formatting and content are aintained when changes are made
in the browser and Web applications can be hosted on the premises running in
SharePoint.

 

Mobile Access Enhancements

View and edit documents from a mobile device even when on the go.

View Office 2010 documents from virtually anywhere by using Web applications,
without losing fidelity, and make changes with limited editing capabilities.

 

Work Offline with an Improved Experience in Microsoft Office Access

Edit Office Access 2010 forms, reports, queries, and macros offline and
synchronize changes in SharePoint when reconnected to the network.

Data in SharePoint 2010 list is cached in the Access 2010 by default.

 

Collaborate Offline and Online

Work offline with SharePoint contents and when reconnected to the network, changes
are synchronized.

Work offline in SharePoint 2010 document libraries and lists through SharePoint
Workspace 2010.

 

Fill In Forms Offline

SharePoint list forms are synchronized so people can work offline.

SharePoint 2010 list items open in an InfoPath 2010 form that is hosted in SharePoint
for edit in display mode.

 

Extend the Reach of Forms

Fill in InfoPath 2010 forms in a Web browser, while online or offline, and from a mobile device.

The InfoPath 2010 forms solution offers embedded solutions that use InfoPath
controls that can be hosted.

 

Publish Access Databases to the Web

Securely publish database applications to the Web so IT managers can meet data
compliance, backup, and audit requirements.

While publishing data, Access 2010 checks for incompatible objects and builds a
report of any runtime differences between the client and server.

 

Use Business Data Applications

Design forms for SharePoint that create, read, update, and delete business data
from a back-end system.

Business data applications start with an external list in SharePoint 2010 and
use InfoPath Designer 2010 to create custom forms on top of the list.

 

Offline and Online
LOB
Integration

Take LOB data offline and synchronize changes automatically when back online.

Synchronize LOB data in both directions between SharePoint Workspace 2010 and
enterprise
line-of-business systems by bringing LOB data into SharePoint 2010 Sites and
then taking it offline via SharePoint Workspace 2010.

 

Enhance Information Security and Integrity with Digital Signatures

Help ensure the integrity of information contained in forms with the controls
necessary to enable single, co-sign, and counter-sign scenarios for the full
form or portions of the form.

InfoPath 2010 and SharePoint 2010 support CNG digitally signed content.

 

Manage Forms More
Easily

 

More easily manage form versions, updates, and upgrades in SharePoint to ensure
that team members are working in the correct version of a form.

Automate template version management with SharePoint 2010 and InfoPath 2010 to
provide
an improved process for checking for template updates.

 

 

Use Line of
Business data in
applications

 

Provide a SharePoint-based framework for creating Office Business Applications.

Business Connectivity Services (BCS) provides the read/write capability to
connect
SharePoint 2010 and Microsoft Office client applications to external data
sources (such as SQL, Oracle, SAP, CRM, Siebel, Web services, and custom
applications).

Use Business Data Catalog within SharePoint to provide read access and surface
line of business information in Office client applications

 

Business Connectivity Services:
Use Data as Document Properties

 

Insert
LOB data as document properties to make critical information more findable,
perceptible, and re-usable in SharePoint.

Expose
BCS data as Word 2010 document properties and insert it into documents.

Package and More
Easily Move
SharePoint Applications

Move
InfoPath applications more easily from site to site and server to server.

 

Package
InfoPath 2010 applications more quickly and easily packaged by using Windows
SharePoint Services solutions (.wsp) and SharePoint site template (.stp) file
formats.

Content Management

Feature Name / Area

MOSS 2007

Sharepoint 2010

Compliance Everywhere

 

New

Flexible
Records Management

 

New

Shared
Content Types And Managed Metadata Service

 

New

Content Organizer

New

Rich Media Management

 

New

Document Sets

 

New

Word Automation Services

 

New

Support For Accessibility
Standards

 

New

Search

Feature Name / Area

MOSS 2007

SharePoint 2010

People And Expertise Search

 

Search From Windows 7 And Windows Mobile

Common Connector Framework For Indexing And Federation

Scale And Performance Via Improved Topology Architecture

Ability To Build Search-Powered Applications

Refinement Panel And Sorting

 

New

Search In Context

 

New

Social Behavior Improves Relevance

 

New

Thumbnails, Previews, And View In Browser

 

New

 

Information

Feature Name / Area

MOSS 2007

SharePoint 2010

KPI Details

 

New

Dashboard Designer

Enhanced Navigation, Including Filtering And Sorting
(Top/Bottom 10, Switchable Measures)

 

New

Publish More Workbooks

 

New

Javascript Object Model

 

New

Powershell Scripting

 

New

Richer Fidelity With Excel Workbooks

 

New

Support For Analytical Services Formatting

 

New

Additional Data Sources, Including External Lists And
“PowerPivot” Workbooks

 

New

Improved Strategy Map Connection And Formatting

 

New

Seamless Management Of Dashboard Content

Integrated Filter Framework

 

New

Calculated KPIs

 

New

Improved Visualizations

 

New

Chart Web Parts

 

New

Business Intelligence Center

(Report
Center)

New

 

Services

Feature Name / Area

MOSS 2007

Sharepoint 2010

Browser-Based Customizations

  

Business Connectivity Services

 

New

Sharepoint Designer

Human Workflows

Forms Services

Visio Services

 

New

Access Services

 

New

Sandboxed Solutions

 

New

Localization Techniques in SharePoint

Friday, November 5th, 2010

Hi, working with SharePoint is an altogether different experience. As a SharePoint developer, I have learnt that there is not only a ‘right’ or ‘wrong’ way of doing things, there is also a third called the ‘SharePoint’ way :) and here is the SharePoint way of implementing Resource files.

This blog describes various localization techniques that are available with SharePoint especially when we implement multilingual solutions. It also highlights different locations where resource files can be deployed and the purpose of deploying in those locations. This article does not cover the basic localization concepts of ASP.Net but rather gives an insight of localization with respect to SharePoint.

With SharePoint (WSS 3.0) resource (.resx) files can be used in different ways and placed in different locations depending upon the particular SharePoint entities that are being localized. The locations that you can deploy the resource files (Global) are
1. 12/Resources
2. 12/Config/Resources
3. VirtualDirectories//App_GlobalResources

We may require splitting our resource files and deploying to the above locations fulfilling the requirements.

If we require localizing the Site and List Definitions, the corresponding resource files should be located in the 12\Resources folder. The XML files in the definition are localized during the provisioning time.

Features can have resources located in the ..\12\Features\\Resources folder.


<Feature  Id="EF06C3BF-07C2-4609-A377-6DA185151F29"
Title="$Resources:InstanceWeb,ListTitle;"
Description="$Resources:InstanceWeb,ListFeatureDesc;"
Version="12.0.0.0"
Hidden="FALSE"
Scope="Site"
DefaultResourceFile="core"
ReceiverAssembly="InstanceWeb, Version=1.0.0.0, Culture=neutral, PublicKeyToken=de1875f396efdf60"
ReceiverClass="InstanceWeb.InstanceResources"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
</ElementManifests>
</Feature>

To provide resource files at Web application level and custom pages, they should be located in the ..\12\CONFIG\Resources folder. When a web application is created, all the resource files from this location are copied to the App_GlobalResources folder of the virtual directory.

Web parts and custom pages:

– can have their resources compiled into their own set of resource dlls which can then be located either in the GAC, or in a sub-directory of the bin folder

– can have their resources located in their assembly’s wpresources folder which can be accessed through the ClassResourcePath method

But in the multilingual solutions, where we store the labels of various languages in the resource files, for example, the text of the links on the page footer in different languages, the field labels on a custom page in multilingual scenarios, text of the items in the dropdown lists etc, are compiled to satellite assemblies and during packaging, deploying the solutions, these assemblies are added to GAC.

I wanted to make use of these resource files so that any update to these files, does not require assembly deployment and the changes should be reflected immediately.

We can achieve this by using App_GlobalResources folder and avoiding the satellite assemblies to be added to GAC.

Visual studio creates the satellite assemblies when we compile the .resx files. I have created a ddf file excluding the entries for the satellite assemblies, so that when we package the solution, wsp file will not contain the assemblies.

How to deploy the files to App_GlobalResources folder using wsp? Yes, include the files in a feature folder and programmatically add the files using feature receiver.


public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPSite site = properties.Feature.Parent as SPSite;
if (site != null)
{
SPWebApplication webApp = site.WebApplication;
string _SourcePath = SPUtility.GetGenericSetupPath("Template") + "\\FEATURES\\" + properties.Definition.DisplayName;
foreach (SPUrlZone zone in webApp.IisSettings.Keys)
{
//the settings of the IIS application to update
SPIisSettings settings = webApp.IisSettings[zone];
//determine the destination path
string destPath = Path.Combine(settings.Path.ToString(), "App_GlobalResources");
//get the RESX files from the feature directory
string[] filePaths = Directory.GetFiles(_SourcePath, "*.resx");
//copy/overwrite the RESX files into the App_GlobalResource directory
foreach (string filePath in filePaths)
{
string fileName = Path.GetFileName(filePath);//get the filename of the file to copy
File.Copy(filePath, Path.Combine(destPath, fileName), true);//copy it over the file in the Resource directory
}
}
}
}

The resource file entries can then be accessed from the HTML or code behind of master pages, custom pages, publishing layouts, user controls and web part pages


<ul class="footernav" id="Links" runat="server">
<li id="Item4" runat="server"><asp:Literal Text="<%$Resources:Footer,About_Us%>" runat="server" /></li>
<li id="Item5" runat="server"><asp:Literal Text="<%$Resources:Footer,Press_room %>" runat="server" /></li>
<li id="Item6" runat="server"><asp:Literal Text="<%$Resources:Footer,Careers%>" runat="server" /></li>
<li id="Item7" runat="server"><asp:Literal Text="<%$Resources:Footer,Customer_services %>" runat="server" /></li>
<li id="Item8" runat="server" visible="false"><asp:Literal Text="<%$Resources:Footer,Contact_Us%>" runat="server" /></li>
</ul>

//Reading language-specific values from resource files
string StrUrl = GetGlobalResourceObject("InstanceWeb", "FooterURL").ToString();
string Fdesc = GetGlobalResourceObject("InstanceWeb", "FooterDesc1").ToString();
string Fdesc1 = GetGlobalResourceObject("InstanceWeb", "FooterDesc2").ToString();

But how the values from specific language resource file are retrieved dynamically?

When a page is loaded in specific language site, the site locale will be already set to specific language. We need to set the Thread culture to the site locale, so that appropriate language resource file is used to retrieve values.


protected void Page_PreInit(object sender, EventArgs e)
{
//Assign the current culture
Thread.CurrentThread.CurrentUICulture = SPContext.Current.Web.Locale;
}

The above step is important to retrieve the values specific to a language. In this way, now if we update the resource files in App_GlobalResources, the changes are reflected on the site, without deploying the dlls.

Happy SharePointing :)

Mandelbrot fractal viewer in Flash Actionscript 3

Monday, October 4th, 2010

Geek that I am, I have always been fascinated with the Mandelbrot set for as long as I can remember. I spent hours and hours as a kid viewing it on Fractint on my dad’s 486 and subsequently have written viewers in C# .Net, TurboPascal, Silverlight, Java, JavaScript, BBC Basic and the Casio 7400g. Having recently done a lot of work with Flash, I decided to try one in ActionScript 3.

Below is the latest version of the application. Click to zoom.

Flash 10 required!

The panel on the right controls the rate of zoom, the lower middle panel controls the iteration bailout value (set this to higher when zooming to stop smaller fractals appearing ‘blobby’) and the lower left panel controls the palette cycling mode (N.B. this is still a bit glitchy but I hope to improve on this)

I discovered that there were some unexpected pay offs in using ActionScript: 

  • The zoom function was extremely easy to program using the inbuilt Flash tween classes.
  • Palette cycling. The early version of the fractal browsers that I have used had some kind of palette cycle mode. When implementing this project, I discovered the paletteMap() function of the bitmapData class and this demonstration. However the documentation of the function isn’t that in-depth, as such this is an early version of the palette cycling mode. I hope to soon fully understand how the palette map function works, and to post an explanation.
  • Little touches to the user interface are very easy to create (although possibly much easier using Flex)

As well as some hindrances:

  • The lack of real threading in AS 3 makes it hard to code. Basically, because the process of generating the fractal takes quite a long time, it locks up the application whilst this is running. The method I used for working round this was to pause the calculation every so often using the setInterval() method to wait (which would give the graphics time to re-render)
  • No useful built in collection framework in AS 3 and I didn’t reuse an existing collection framework because the object of the exercise was coding it all myself, however I hope to refactor this soon.

Accelerated Game Programming with HTML5 and canvas

Monday, September 6th, 2010

Welcome to my short tutorial about HTML5 game programming. I’ll try to briefly explain how to create simple games using HTML5, canvas elements and JavaScript. Some code will be omitted during this tutorial but feel free to view my game demo – I have intentionally not minified the source code.

HTML5 comes with lots of fantastic features such as :

  • canvas element
  • video and audio support
  • local storage
  • offline web applications
  • geolocation

…and much more. I won’t be covering HTML5 specifications in this post but you can read more about HTML5 here : http://diveintohtml5.org/.

Games were created in HTML before HTML5 so why write this post now, did anything change? Well yes, <canvas> elements come in very handy when creating client-side games.

Canvas and JavaScript can be used to draw and animate game elements easily.

Typical Game class

Before we start with our game implementation and canvas elements I would like to quickly show you the structure of a typical Game class:

function Game() {
this.Initialize = function () {
// initialize all game variables
}
this.LoadContent = function () {
// load content – graphics, sound etc.
// since all content is loaded run main game loop
// Calls RunGameLoop method every ‘draw interval’
this.GameLoop = setInterval(this.RunGameLoop, this.DrawInterval);
}

this.RunGameLoop = function (game) {
this.Update();
this.Draw();
}

this.Update = function () {
// update game variables, handle user input, perform calculations etc.
}

this.Draw = function () {
// draw game frame
}
}

This is a typical JavaScript game skeleton. Interesting bit here is the “setInterval” method. When all resources are loaded, we can start the main game loop, collect user input, perform calculations and render our game every X ms. This is needed for games that perform some calculations in the background, AI movement, animations etc. For more static games that need to redraw content only based on user input we can modify this skeleton class and get rid of the game loop.


function Game() {
this.Initialize = function () {
// initialize all game variables
}

this.LoadContent = function () {
// load content – graphics, sound etc.
var ourGame = this;
$(document).bind('keyup', function (event) {
ourGame.Update(event);
ourGame.Draw();
});

}

this.Update = function (event) {
// update game variables, handle user input, perform calculations etc.
}

this.Draw = function () {
// draw game frame
}
}

Here both the game update and redrawing will happen only in response to user input. This approach is less CPU intensive but is only possible for simple games.

I’m going to show you an example of a quite simple, classic game that we all know: Sokoban. There are lots of sokoban clones made for every available platform but I haven’t seen any written using canvas elements yet.

Getting started

Let’s start with creating our HTML5 page with a single canvas element:


<html>
<head>
<title>Sokoban</title>
</head>
<body>
<canvas id="canvas" width="800" height="500">
Canvas not supported.
</canvas>
</body>
</html>

That’s it! Now we can see… a blank page in the browser supporting canvas elements: Chrome, Firefox and Safari are “Canvas not supported” in Internet Explorer 8 and older versions.

Before we can start drawing on canvas we need to get the drawing context. Canvas exposes one or more drawing contexts but we will focus on the most popular and supported one – “2d” context.

Let’s add a reference to JavaScript file straight after our closing canvas tag:

<script type="text/javascript" src="../Scripts/test01.js"></script>

This is part of this JavaScript file.


var _canvas = document.getElementById('canvas');
var _canvasContext = null;
//check whether browser supports getting canvas context
if (_canvas && _canvas.getContext) {
_canvasContext = _canvas.getContext('2d');
// ... drawing here ...
}

I will quickly cover canvas context drawing methods that will be used during this tutorial. The only methods that we need are :

  • drawImage(img, x, y);
  • fillRect(x, y, width, height);
  • strokeRect(x, y, width, height);
  • fillText(‘Text’, x, y);

Note: It’s important to remember that canvas has it’s beginning (0,0) in upper left corner.

Those methods are very straight-forward. drawImage is drawing a specified Image object or <img> on canvas in location specified by x, y. fillRect and strokeRect are both used for drawing rectangles, the only difference is that the first method is drawing a rectangle filled with colour and the second one is drawing an empty rectangle with coloured border. fillText is used to put text on canvas.

A working demo can be found here: http://demo2.felinesoft.com/Sokoban/Home/Test01

JavaScript source that is rendering our 2 rectangles, text and an image can be found here:

http://demo2.felinesoft.com/Sokoban/Scripts/Test01.js

This is how the test page should look like :
Test page 01

Double buffering

Since we now have a game skeleton and know how to draw on canvas the only thing that is left before actual game implementation is double buffering. In our game double buffering does not come in that handy since we won’t have any animating effects that can flicker, but since this post should be your starting point in the land of canvas game programming I figured that I’ll quickly show you how to implement simple double buffering on canvas.

The idea behind double buffering is to reduce flickering by first drawing in memory buffer and later drawing the entire image from the memory onto the screen.

We only need to modify our canvas JavaScript slightly:

_canvas = document.getElementById('canvas');
if (_canvas && _canvas.getContext) {
_canvasContext = _canvas.getContext('2d');
_canvasBuffer = document.createElement('canvas');
_canvasBuffer.width = _canvas.width;
_canvasBuffer.height = _canvas.height;
_canvasBufferContext = _canvasBuffer.getContext('2d');
}

Now instead of drawing on _canvasContext object we should draw on _canvasBufferContext and after the drawing is done call just one line:

_canvasContext.drawImage(_canvasBuffer, 0, 0);

This will draw whole content of our canvas buffer onto the screen and that’s it!

So what exactly are we trying to write?

We need to write a simple Sokoban game. The goal of the game is to move all “boxes” to marked fields. Game rules:

  • Boxes can only be pushed, not pulled.
  • Only one box can be moved at a time

For more information about Sokoban visit: http://en.wikipedia.org/wiki/Sokoban

We will need to create a few JavaScript classes for our game :

  • Main “Game” class
  • “Map” representation
  • Player
  • Map statistics – this will need to display level number, number of moves / pushes performed
  • Class for every “drawable” element :
    • Wall
    • Box
    • Box on Goal
    • Floor
    • Empty space
    • Goal
    • Image Repository – this class will be storing all images used in our game. Instead of loading and creating new instance of Image we will be able to get our images from here.

Map representation

In my example all maps are stored in one XML file. I’m using the following format:


<?xml version='1.0'?>
<Levels>
<Level No="1" Width="19" Height="11">
<Row>    #####</Row>
<Row>    #   #</Row>
<Row>    #$  #</Row>
<Row>  ###  $##</Row>
<Row>  #  $ $ #</Row>
<Row>### # ## #===######</Row>
<Row>#   # ## #####  ..#</Row>
<Row># $  $          ..#</Row>
<Row>##### ### #@##  ..#</Row>
<Row>    #     #########</Row>
<Row>    #######</Row>
</Level>
....
</Levels>

Explanation of character representation:

  • ‘#’ – wall
  • ‘$’ – box
  • ‘ ‘ or ‘=’ – empty space
  • ‘ ‘ – Floor
  • ‘@’ – player
  • ‘.’ – goal
  • ‘*’ – box on goal
  • ‘+’ – player on goal

I’ve created a base class for all elements that can be drawn:


function DrawableElement() {
this.GetImage = function () {
//implement this method in your sub-class if your element is represented by image
//this should return an Image object
return null;

}

this.GetFillStyle = function () {
//implement this method in your sub-class if your element is represented by filled rectangle
//this should return canvas "fillStyle" string
return null;

}

this.ImageRepository = null;

}

Sample sub-class (ImageRepository implementation omitted but can be found by looking at demo page source files):


function Floor(){
this.GetImage = function () {
return this.ImageRepository.Floor;
}
}

JavaScript inheritance creation:


Floor.prototype = new DrawableElement();
Floor.prototype.constructor = Floor;

I’m using very simple WCF service to return a specific level. You can store each level in a separate XML file, just change ajax url parameter to url path pointing to your xml file, for example:

“http://<domain>/level_” + levelNumber +  “.xml”,

It’s very easy to access web service or direct xml file using jQuery :


$.ajax({
type: "GET",
url: "http://localhost/SokobanWCF/SokobanService.svc/GetMap/" + levelNumber,
dataType: "xml",
success: this.ParseXmlMap,
context: this

});

jQuery is also very useful for parsing XML, the following code demonstrate how a map can be constructed ( part of ParseXmlMap method ):


$(xml).find("Row").each(function () {
var wall = false;
var row = $(this).text();
for (var x = 0; x < mapWidth; x++) {
// some rows are shorter than map width - fill rest with Empty elements

if (x >= row.length) {
mapRef[x][y] = new Empty();
} else {
switch (row[x]) {
case " ":
// if we had wall already that mean we need to insert a Floor element,
// for Empty elements that are between walls on some maps we are using '=' character
if (wall) {
mapRef[x][y] = new Floor();
}
else {
mapRef[x][y] = new Empty();
}
break;

case "#":
mapRef[x][y] = new Wall();
wall = true;
break;

case "$":
mapRef[x][y] = new Box();
break;

(...)

As you can see each map/level is represented using two dimensional Array. I’m iterating through every XML element – <Row> and later through every character within the row value.

Since downloading and parsing XML document can take a while I’m using a “Loaded” flag on Map object to determine whether document parsing has ended and the map is ready to be draw. In my Game class in LoadContent method I’m setting the timer to check whether map is ready ( every 50 ms ) :


this.InitialUpdateDraw = setInterval(this.InitialUpdateRun, this.CheckInterval);

and InitialUpdateRun method :

this.InitialUpdateRun = function (ev) {
if (_map.Loaded && _imageRepository.Loaded()) {
document.sokobanGame.Update(ev);
document.sokobanGame.Draw();
//we don't need timer anymore
clearInterval(document.sokobanGame.InitialUpdateDraw);
}

}

This is needed since when the level is loaded we need to update game variables and display the level. Later, all game Update and Draw methods will only be called after user performs some sort of action.

Updated method for Map is very simple. We only need to check for end game conditions and update number of moves / pushes.


this.Update = function () {
//check for end game conditions
if (this._goals > 0 && this._goalsAchived == this._goals) {
this.Finished = true;
}

_levelStatistics.Update();
}

Finally the Map Draw method. Thanks to DrawableElement base class and inheritance we just need to iterate through the two dimensional Array and the correct image will be draw for each element because of our JavaScript implementation of Polymorphism.


this.Draw = function (canvasContext) {
var xCanvasPos = 20;
var yCanvasPos = 20;
var tileSize = 30;

for (var y = 0; y < this._height; y++) {
xCanvasPos = 20;
for (var x = 0; x < this._width; x++) {
var img = this._map[x][y].GetImage();
if (img != null) {
// draw image
canvasContext.drawImage(img, xCanvasPos, yCanvasPos);
} else {
// draw rectangle
canvasContext.fillStyle = this._map[x][y].GetFillStyle();
canvasContext.fillRect(xCanvasPos, yCanvasPos, tileSize, tileSize);
}

xCanvasPos += tileSize;

}
yCanvasPos += tileSize;
}
// this is used to properly position level statistics according to the level
this.OnScreenWidht = xCanvasPos;
this.OnScreenHeight = yCanvasPos;
_levelStatistics.Draw(canvasContext);
}

Player movement

Player movement is being handled on keyup event. I used WASD buttons to handle user movement. Just as a reminder W = up, S = Down, A = Left, D = Right.

Move direction is represented by MoveDirection enumeration.

Handler method for user movement :

this.KeyCheck = function (event) {
var KeyID = event.keyCode;
switch (KeyID) {
case 87: // W
this.Move(this.MoveDirection.Up);
break;

case 65: // A
this.Move(this.MoveDirection.Left);
break;

case 68: // D
this.Move(this.MoveDirection.Right);
break;

case 83: // S
this.Move(this.MoveDirection.Down);
break;

}

}

Obviously the user cannot move two boxes or go through walls. We need a method to validate the user movement:


this.ValidateMove = function (targetCell, nextCell) {
var posToMove = targetCell.constructor;
if (posToMove == Wall) {
// wall is next, player cannot move there
return false;

}

var nextObject = nextCell.constructor;
if ((posToMove == Box || posToMove == BoxOnGoal) && (nextObject == Wall || nextObject == Box || nextObject == BoxOnGoal)) {
//player attempts to push box, if the next element after the box is wall or another box – player cannot move
return false;
}

return true;

}

The only interesting bit here is the “constructor” property. This property returns a function that was used to create object stored in this cell. That way we can easily check what type of elements surrounds the player.

In previous section, while creating Wall, Floor and DrawableElement base class I’ve created inheritance using the following way:

Floor.prototype = new DrawableElement();
Floor.prototype.constructor = Floor;

Second line is very important here, without this line returned function for Floor object would be DrawableElement…this would prevent us from using move validation as described above.

I’ll omit the full code responsible for changing player position; it’s just assigning player object to new position on our two dimensional array and can be viewed by examining source code on the demo page.

Level finished and loading new level

I used cookies to be able to load and save previous state for the user; after a level is finished I’m inserting a cookie specifying the level that needs to be loaded. LoadContent is reading the cookie and loading the right map. That way the user can close browser and come back to the same level later. Loading and saving of cookies is handled by cookie plugin that can be found here: http://plugins.jquery.com/project/cookie

I’ve also added “Congratulations” popup when user finished level with a button saying “Go to the next level”. Automatic map loading seemed to me not very user friendly.

My sokoban clone contains 40 classic levels so it’s very possible that user won’t be able to finish them all during one session.

Finally!

View Demo

I wanted to make this blog post as brief as possible. It turned out quite long but finally we are at the end of our journey. This is how our game looks; see the image below or visit View Demo.

I’ve skipped some code during this “Accelerated” tutorial but I left it non-minified so it can be viewed by looking at live demo source code.

finished game

What next?

Possible game improvements that are out of scope of this tutorial:

  • High score list ( after level is finished POST number of moves and pushes to the WebService and store them in Database, later display top 5 best scorers for every level )
  • Undo move option.
  • More secure end game conditions check. Currently it’s very easy to start with map level 40.
  • In case you want to give ability for the users to navigate between levels, don’t worry about previous point – implement level selection instead.
  • Ability to upload your own maps and share them with friends.

Hope you’ve enjoyed reading this post and it gave you a bit of insight into what game programming in HTML5 looks like.

SMTP Configuration and e-mail deliverability

Tuesday, May 11th, 2010

Prerequisite:

Server with Windows Server 2003 / 2008

Sending e-mails is quite straightforward; all modern programming languages have some built-in methods to achieve this task. Delivering an e-mail is a totally different matter.

Probably anyone that has ever had any dealing with websites sending e-mails has faced the problem where the e-mail is ending up in Spam/Junk box or not being delivered at all.

There are a few ways to improve e-mail deliverability. The path to achieve sensible e-mail deliverability can be long and bumpy. It includes:

1)      Choosing  the domain registrar

2)      Setting up the DNS

3)      SMTP service configuration

4)      Setting up sender authentication technologies

5)      Where to go next? (E-mail content, best practices, blacklists)

1   Choosing the domain registrar

Oddly enough – not all domain registrars allow creating / modifying TXT records. This is the absolute minimum for our DNS configuration – all e-mail authentication technologies require new TXT records in your domain.

This list captures domain registrars that support TXT records:

http://www.kitterman.com/spf/txt.html

123-reg is on that list, let’s try creating a domain there or better not, unless you want to spend hours stressing over why your sender’s authentication is not working.

As we can see 123-reg is not supporting DKIM which is weird since DKIM entry in DNS is just a normal TXT record. But sadly it’s not working … DKIM entries will not be found while using 123-reg. For most users it’s ok that they can only add SPF. But I decided to find a different domain registrar. I found quite few that are supporting DKIM entries (some of them directly through web-panel, some by support requests)

  • Bluedomino
  • DNS Made Easy
  • GoDaddy
  • Media Temple
  • Network Solutions
  • Pair
  • Register.com
  • Textdrive
  • Melbourne IT

I’ve chosen GoDaddy, but feel free to pick any other provider or stick with your current one if you don’t need DKIM.

2   Setting up DNS

There are 2 important things to take into account while setting up your DNS:

  • Your A record must point to your sending server’s IP address – this can be done from your DNS management panel.
  • Your PTR record must point to your domain – to change PTR you need to have IP assigned to you by your hosting company, not all hosting companies allows you to change PTR record, but most of them will change it for you when you send a support ticket.

Now let’s have a look at our settings.

MX records are responsible for the specifying mail server that is in charge of accepting e-mails. While sending e-mails the recipient server should not look at MX records, but if you want to receive e-mails you need to add server’s domain names which can accept e-mails.

To test your DNS settings you can use a very useful tool provided by mxtoolbox :

http://www.mxtoolbox.com/SuperTool.aspx

With it you can easily type commands like “a:<your domain name>” or “ptr:<your IP address>” and check whether the A record is resolving to your IP and whether your IP is resolving to your domain name.

Below you can see the results from mxtoolbox check:

3  SMTP service configuration

I assume that you have IIS SMTP service. Please note that under IIS7 SMTP service is still available though IIS6 management console.

First let’s enable the connection with our SMTP service through localhost.

This can be done by going to Properties of our SMTP service. On the bottom of the second tab ( Access ) we need to open “Relay…” window and add 127.0.0.1 which is a localhost address.

Another step is to set a fully-qualified domain name for our SMTP service. This will be used for HELO and EHLO handshakes. Let’s go to 4th tab ( Delivery ) and click “Advanced…”. We need to specify how our SMTP server should “introduce” itself.

Since we have everything ready let’s test our e-mail.

Posrt25 is providing us with an excellent tool for e-mail testing:

http://www.port25.com/domainkeys/

As you can see from the article above, we have 2 ways of e-mail testing:

  • “If you wish to receive the results at the address in the “mail_from,” the sample message should be sent to check-auth@verifier.port25.com.”

One of the ways to send an e-mail is to use telnet.
Using telnet can be useful for a simple e-mail tests but it can cause some errors later on. As for now let’s try using telnet.

Let’s quickly go through the screenshot.

  • EHLO / HELO <your domain name>
    Response should be 250 OK
  • Specifying sender e-mail address ( mail from ):
    mail from: <your sender e-mail address>
    Response : 250 OK
  • command : data will enable you to write e-mail headers and body. You can now specify headers like ‘From display name’, ‘Subject’ and message itself (body). We are only interested in ‘From display name’ so we can put e-mail address
    type:
    From: <email address where you want to receive the report>

    press “Enter”, Type “.” and “Enter” again.

After a few seconds, up to a minute, you should get an e-mail with a report. It will probably look something like this:

This means that we neither have SPF record, DomainKeys, DKIM nor Sender-ID authentication. SpamAssassin marked our e-mail as “ham” which is opposite to spam so it has been categorised as non-harmful e-mail.

One more important thing while configuring SMTP service is that it cannot be open-relayed. Open mail relay means that anyone (including all sorts of spammers) can send e-mails through your server, which is a very bad situation and should be avoided at all costs.

There is plenty of on-line services that can check whether your site is open-relay but for our example let’s use mxtoolbox again.

You can open link from before (http://www.mxtoolbox.com/SuperTool.aspx ) and type command smtp:<your domain name>

Or you can also use this link: http://www.mxtoolbox.com/SuperTool.aspx?action=smtp:<your_domain_name_here>

Result should look similar to this:

4  Setting up sender authentication technologies

  • SPF ( Sender Policy Framework ) and Sender-ID

These two are giving the option to specify which server is allowed to send e-mails for a given domain. This is done by modifying the domain DNS record.

For example you can add a new TXT record to your domain with a value “v=spf1 a ~all”.

which means that:

v=spf1 // we are using version 1 of SPF

a // domain must have A record that can be resolved to sender address

~all // (Soft Fail) Mail may possibly come from an IP address which does not match result from resolving A record (our example), but this kind of e-mail will have bigger chances to go to spam box.

Other common parameters are:

“v=spf1 a -all” // ‘-all’ mean that if an e-mail originates from address not present in domain’s A record it will go to junk or will be rejected

“v=spf1 a ip4:<sender server ip> ~all” // ip4:<sender server ip> ( please replace <sender server ip> with public IP address of your server ) means that every host in this IP4 range can send e-mails.

Let’s add sample TXT entry to our DNS:

There are 2 very good wizards that can guide you through the process of creating a correct record:

http://old.openspf.org/wizard.html

http://www.microsoft.com/mscorp/safety/content/technologies/senderid/wizard/

Sender ID is using the same sender validation method, syntax and they both need to be published as new TXT records in DNS. It doesn’t need to be published in your DNS since SPF is compatible with Sender ID, but it all depends on the receiving server.

Sender ID is not really popular, even Microsoft is using SPF in his “Sender ID wizard”, but you can always publish Sender ID record.
For example :

“v=spf1 a ip4:<sender server ip> -all”

Written as Sender ID record :

“spf2.0/mfrom ip4: <sender server ip> -all”

You can submit your SPF record to be added to Sender-ID program (again it looks like real Sender-ID record is not needed ) using this link :

https://support.msn.com/eform.aspx?productKey=senderid&page=support_senderid_options_form_byemail&ct=eformts&wa=wsignin1.0

After setting only SPF record let’s try to send e-mail to our port25 to validate our configuration. The results are:

SPF – passed, that’s good.

Sender ID – neutral? It’s because we were sending an e-mail using the same telnet technique as before with ‘From field’ set to different e-mail address.

From now on I would recommend sending e-mails from your own application. Some very simple C# code for sending e-mails:

using System;
using System.Net.Mail;
namespace Email
{
  class Program
  {
    static void Main(string[] args)
    {
      Console.WriteLine("Type from address (and hit Enter):");
      string fromAddress = Console.ReadLine();
      Console.WriteLine("Type from name (and hit Enter):");
      string fromDisplayName = Console.ReadLine();
      Console.WriteLine("Type Recipient address (and hit Enter):");
      string toAddress = Console.ReadLine();
      Console.WriteLine("Type subject (and hit Enter):");
      string subject = Console.ReadLine();
      Console.WriteLine("Type body (and hit Enter):");
      string body = Console.ReadLine();
      MailMessage Mail = new MailMessage();
      MailAddress ma = new MailAddress(fromAddress, fromDisplayName);
      Mail.From = ma;
      Mail.To.Add(toAddress);
      Mail.Subject = subject;
      Mail.Body = body;
      Mail.Headers.Add("Reply-To", fromAddress);
      try
      {
        SmtpClient smtpMailObj = new SmtpClient();
        smtpMailObj.Send(Mail);
        Console.WriteLine("Email sent, press enter to exit.");
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
        Console.WriteLine(ex.StackTrace);
      }
      Console.ReadLine();
    }
  }
}

We will also need app.config for our small Console Application :


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.net>
<mailSettings>
<smtp>
<network host="localhost" port="25"/>
</smtp>
</mailSettings>
</system.net>
</configuration>

This of course is not production code, this is simply code that you can use for test applications. Sender-ID will fail because of invalid ‘From address’. We will need a POP3 account on our server to set a proper ‘From address’ and receive e-mail report s back to our server.

After setting up POP3 and using our Console Application we will get result like this:

This is what we wanted.

We will discuss setting up POP3 in the next section.

  • DomainKeys and DKIM

Another approach to authenticate sender is DKIM, which was created by DomainKeys (developed by Yahoo!) merged with IIM ( Cisco ). Both technologies are using cryptographic signature generated from an e-mail header and body. That signature is then passed along with the e-mail to the receiving server, which validates signature against published DNS information.

In this article we will try to implement only the DKIM. There is a small problem with Windows build-in SMTP service – it does not support DKIM signing.
What are our options then? You could manually add cryptographic key in C# code, or you could write an application that will be adding the signing and still use the built in SMTP service or finally you could use 3rd party Mail server / plug-in. That last option is recommended and at the same time is the simplest. There are many commercial mail servers ( or plug-ins that integrate with existing Windows SMTP service ).

Commercial plug-in that will allow you to use your existing server configuration: http://www.emailarchitect.net/domainkeys/

Free mail server ( SMTP, POP3 and IMAP ) with DKIM support:

http://www.hmailserver.com/

Those are only a few options out of many available. Feel free to find most suitable solution for you. In this article we will go with hMailServer.

Before installation you should disable Windows SMTP service. An installation tutorial and basic configuration can be found here: http://www.hmailserver.com/documentation/latest/?page=howto_install

http://www.hmailserver.com/documentation/latest/?page=basic_configuration

Now we have everything set up: we are running our new SMTP service, we have POP3 service and our Consol Application available for tests. Let’s add DKIM.

There are many tools to generate public / private keys for DKIM. I’ve chosen a quick on-line way:

http://www.socketlabs.com/services/dkwiz

You will need to specify your domain name and selector which can be any word you’d like.

Your generated result should look similar to this:

Steps that we need to carry out now are quite simple:

  • Add two new TXT records to your DNS as described on the page with generated DKIM keys. Create new private key file ( any text file ). File needs to include ‘begin tag’ (—–BEGIN RSA PRIVATE KEY—– ), key and ‘end tag’.
  • Open hMailServer administration and navigate to your domain. You should be able to see DKIM on the 5th tab. Add your private key file and then specify selector. Header and Body method should be set to “Relaxed”, Signing algorithm to SHA256.

Configuration should look similar to that:

We can easliy test whether our DKIM has been properly set in DNS by visiting those pages:

http://domainkeys.sourceforge.net/policycheck.html

http://domainkeys.sourceforge.net/selectorcheck.html

Results:

Note: Don’t forget to remove “t=y” from your TXT record after you finish testing DKIM (t=y means that domain is in test mode).

Since everything is set let’s send a test e-mail again. Let’s use our test application and since we have POP3 server configured let’s send an e-mail to check-auth@verifier.port25.com.

Note: all received e-mails can be found physically on the server by navigating to
<installation path>\hMailServer\Data\<your domain name>\<account address>

If everything is properly configured we should get this report:

This looks better now. Let’s see how Google is ‘seeing’ our e-mail.

Signed-by : saktos.info – that’s what we wanted.

Let’s take a closer look at e-mail source:

SPF, Sender-ID and DKIM have passed. One would think that that’s the end of our journey since mail server is configured. Well not really… even setting everything does not mean that we can send e-mails everywhere with any content and they will always go to the inbox…

5  Where to go next? (E-mail content, best practices, blacklists)

Blacklists are very important part of e-mail deliverability. It doesn’t matter what kind of authentication methods are being used if we appear on the blacklists. They should be monitored on a regular basis. We can again use mxtoolbox for that purpose: http://www.mxtoolbox.com/blacklists.aspx

All e-mail services that filter spam are not only based on authentication or blacklists, but also work by using some advanced content filters. Some very small lists of spam keywords can be found here: http://www.activewebhosting.com/faq/email-filterlist.html

Avoid sending e-mails containing lots of images and never send attachments with some potentially dangerous files like *.exe. If you need to send an attachment it’s better to provide the user with a link to your website than attaching a file.

If you want to do a marketing campaign never buy e-mail addresses. It’s much better to gain e-mail addresses through your own website. Every time a user clicks “Report Spam”, it’s being sent back to the server which is lowering your server reputation.

If your e-mails are still going to the spam box I suggest reading through some very helpful articles:

1)      Direct link to PDF file explaining how to improve deliverability to hotmail

http://download.microsoft.com/download/e/3/3/e3397e7c-17a6-497d-9693-78f80be272fb/enhance_deliver.pdf

2)      Still having problems with hotmail ? Check Hotmail postmaster services:

http://postmaster.msn.com/Default.aspx

3)      CAN – SPAM wiki page. This act contains many best – practices for sending e – mails.

http://en.wikipedia.org/wiki/CAN-SPAM_Act_of_2003

4)      Google bulk messaging guidelines

https://mail.google.com/support/bin/answer.py?answer=81126

How to get a new IT system working for you

Tuesday, December 29th, 2009

Most IT systems are sold into companies on the premise that they will deliver productivity increases and efficiency savings. The idea is that staff will save time through the automation of tasks. Managers will make better decisions with access to the accurate updated information whenever they need it. So why does this often not happen?

 

 This is a complex question with many factors involved, some of which are specific to projects, some of which are more general.  In this short article I will not be able to address all of them by a long way so please feel free to contact me on 0845 658 6767 to discuss them.

 

 The most common issue I have come across is trying to fit your company’s processes into the software rather than fit the software to the company. Although the software will provide productivity saving when compared to the current method used for carrying out the task, the overheads of staff learning the new procedure more than counteracts the productivity gains from the new software. Over time this can be reduced through training or even eliminated so the productivity gains are accessed from the start. This is much easier to achieve if you have staff buy in before the software is rolled out.

 

 This brings me to a similar and related issue- software being forced on a company from the top down. Now don’t get me wrong, software is often strategic rather than tactical, and major decisions like this have to be made by those with a complete view of the company, for example the CEO or CTO. In all cases of software roll-out I would encourage opinions to be canvassed. In the case of off-the-shelf software it can lead to in-sights that would otherwise not have been noticed, affecting which software or modules are purchased. It is amazing how often staff recommend that a module is not purchased. In the case of customized or bespoke software I’m of the opinion it is critical to the successful design of the software that users are interviewed. After all, who is in the best position to comment on software, surely it must be the people who use it? I have gone off on a tangent here about user feedback in customisation and bespoke development so I will cease by saying only that you are kidding yourself if you think you can build a business process application without speaking to the people that perform the tasks. I could write a whole article on this and will at another point so will stop now and come back to the point.

 

 Buy-in- yes that is what I was talking about. Even though the decision is made at the top the users must be willing to take on the software and adapt their behaviour to it, although I hasten to add if your processes are streamlined already you should be changing as little as possible. Through interviews with the people at the coal face so to speak you can get them involved and generate the feeling that they are driving the decision-making processes and in a way they are and that is the point. It will give you the information to do 2 things which are my 2 major points in this article.

 

 1. Customise the software to fit your business.

2. Develop training and manuals that fit your company processes.

 

 This will bring the usefulness of the software in at an early stage and ensure that all the clutter of a huge software manual that makes little sense to most users is by-passed and the information that really matters and delivers those productivity increases is readily available to you and your staff. On the day of go-live you will have created a feel of excitement rather than resentment. The information gained during the interview stage will ensure that the processes are a fit to your company and focused on tasks that were wasting most of your staff’s time.

 

 As I said at the start there are many more issues involved than I have mentioned here and I will try to write more articles to help you all out in the meantime. Good luck with your software and remember it is your software and it should work for you not the other way round.

 

 Ralph Johnson,  FelineSoft