More servicesWindows Live
HomeHotmailSpacesOneCare
 
MSN
Sign in
 
 
Spaces home  .Net ZoneProfileFriendsBlogMore Tools Explore the Spaces community

.Net Zone

September 13

OpenID and CardSpace

OpenID and CardSpace are both complementary and competing technologies.  An interesting thing about OpenID it that it allows you to "attach" a Card to your OpenID account (create an openid at myopenid.com if you have not already).  That is interesting as it allows you to logon to your OpenID account using your InfoCard on your desktop.  That is pretty powerful because that means you can logon to any OpenID site using your InfoCard.  So the web designer that enables OpenID logins will also get CardSpace for free without writing a single line of additional code - that is pretty cool.

In a previous post, I wrote on the need of a Proxy that would allow me to get my Card easily when on a public pc.  OpenID with cardspace support does not get us there, because I still have to have the card on the machine I am at in order to authenticate to OpenID using my card.  However, OpenID does allow me to login using name/pwd pair, so that is always a good last resort.  However this can be made better I think.

What if the OpenID provider also "stored" my Card in encrypted form?  Then I could download that card and use it.  To make this process simple, MS needs to create a temp proxy card.  So on a new machine I create a TProxy card that have my name and a URI to my OpenID provider.  Now when I try to use TProxy card, it downloads my real card from the provider and decrypts by prompting for a password.  Now that I have my real card local, I can then continue to use as normal during the session.  The provider only ever sees my card in encrypted form so it is protected from snooping.  Now the question is how to get rid of local card when done?  If I log out, the CardSpace framework and just clear card memory and be done.  But what if I just walk away and forget to logout?  I guess that is same issue as forgetting your credit card at a store and hoping nobody uses it until you cancel the card.  One option to mitigate the risk is to add a timeout on the card.

I guess another option would be a usb smart card and a pwd pair.  Keep your smart card on your key chain and you can login anywhere.  Loose your card, and someone still needs your password.  So I need to login once (to decrypt the card on the smart card) and can use the card for remainder of my session.

September 12

CardSpace (InfoCard) replay and thoughts

InfoCard (i.e. CardSpace) has been out for a bit, but does not get much joy yet. I think probably cause a lot people just don't know about it or don't care yet.  But the other day I created a OpenID and started using it for identi.ca.  identi.ca is a good example of a site that uses OpenID well and makes it easy.  That got me thinking all sites should use OpenID.  Then I rediscovered CardSpace because OpenID also always you to attach an InfoCard to your id.  So that got me thinking more about CardSpace and using it for my web site.

In general, I am starting to think InfoCard (or the idea of InfoCard) is almost the perfect security model for the following reasons:

1) You control your cards locally. You don't have various names and password strung out all over the INET.

2) You can use same card on multiple sites.

3) You only share the info you want in the card.

4) You get to pick your card at login using a picture and named card.  This makes it easy to remember what card you used at what site. Vista actually has a nice CardSpace control for this and it works well (can download for XP).

5) People can't hack your password on a site using normal hash tables (rainbow) or brute force.  I am not sure yet if it is possible to brute force an InfoCard.

6) It moves the security model to a standard and tested model.  Today, each site may (or may not) protect your password with all kinds of good or no good hash and/or encryption methods.  Point it, you don't know what method is used - it could be stored in the clear!  InfoCard removes many of the server side variants and acts almost like an agent on your behalf.

7) The framework it there where in the future you can time limit your card and revoke it from use.

Given the upsides and the fact that I am in control of the card, I am starting to wonder if OpenID is the right model.

That said, AFAICT, there is one primary down side - you have to have your card on each machine you use.  That means if you are on some random machine, you need to figure our how to get your card and have to worry about removing it from the machine when you done.  Maybe what we need is password protected Temp Proxy Card.  When you are at a "public" PC, you create a Proxy Card that includes the URL of your real card (stored at a public URL that is encrypted AES with your known password).  Then browse to web site that requires a card, the Card selector will popup and you select your Proxy card.  The framework will download and decrypt your real card and use that and cache it in memory only in encrypted form using your same password as your proxy card.  Maybe it also has a time limit on it.

Make your web site InfoCard enabled.  I have looked at a couple solutions, but found Dominick's control the best fit and ease of use.  It also supports non-SSL mode, as many web sites (i.e. blogs) do not use SSL.  Having the option is nice.

Dominick Baier's IC Selector at: http://www.codeplex.com/InfoCardSelector/Release/ProjectReleases.aspx?ReleaseId=12626

August 23

Transaction is not allowed error using ADO.Net Entities.

Doing some ADO.Net Entity queries and updates the other day, I kept getting this exception:

"New transaction is not allowed because there are other threads running in the session."

foreach (Users u in db.Users.Include("Queries"))
{

      // A db.SaveChanges() here will throw the error.
}

 

The reason is we have an open Reader in our foreach and we can't nest trasactions like that.  The solution is to read everything we need first so we close the reader.  The simple solution here is to append .ToArray() like:

foreach (Users u in db.Users.Include("Queries").ToArray())
{

      // A db.SaveChanges() here should work.
}

August 20

ADO.Net Data Services after Silverlight Tools sp1

After installing Silverlight VS Tools SP1 beta, not only did SL designer not work, but it somehow messed up my ADO.Net REST services.  Was getting strange exceptions.  I uninstalled SL Tools and reinstalled VS SP1 (not sure if that was needed) and ADO.Net data services seem to be back working again.  Short story, don't install SL tools yet.  I should say, don't install beta software - but I could not follow my own advice.

August 15

Turn off feed reading view to debug your ADO.Net

If your trying to expose a new ADO.Net dataservice and work some samples, you may get some strange output in your IE that looks like a feed page and wonder why you can't see the XML as the samples show.  Just turn off the feed reading view in IE.

 

image

image

Silverlight Streaming Service

If you have not looked at in a while, the new SL service allows you to directly upload you .wmv files.  So you don't need to use Encoder anymore to encode a SL video into a SL application.  This makes it really simple to public videos for your blogs, etc.  After uploading your video, the service gives you chance to do a quick preview and gives you the html you need to embed the video in your blog.  Simple and elegant - nice.

http://silverlight.live.com

August 14

Microsoft Response Point PBX

Man, I am really excited about the new small business PBX system MS released - Response Point.

It seems like one of those no brainers - Create a platform that can be extended and programmed against easily using .Net, have a blue button and voice commands, connect the phone via Ethernet and IP, and make it super easy to hookup,manage, and buy.  That is a formula for success IMO.  I am looking forward to seeing the SDK.  I can already envision a wave of social apps for this thing.  Now I just need to figure out how to get one to experiment with...

http://www.microsoft.com/responsepoint/

January 09

Enterprise Framework LINQ Queries failing - MSDN Forums

Good Linq post from Colin Meek below:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2078990&SiteID=1 

To give a sense of what is shared and what isn’t between LINQ to SQL and LINQ to Entities (both in terms of modules and behavior) I’ll repeat some information that’s probably familiar to most people on this thread…

LINQ providers support integrated query via the IQueryable and IQueryProvider interfaces. The provider’s job is basically to translate LINQ expression trees into native queries. LINQ to SQL and LINQ to Entities accomplish this translation in roughly the same way, though nothing is shared beyond the System.Linq components in System.Core.dll.

Matt Warren’s IQueryable series gives a more detailed overview (http://blogs.msdn.com/mattwar/archive/2007/07/30/linq-building-an-iqueryable-provider-part-i.aspx) but I’ll include the highlights here to provide some context:

1. At compile time, user code is translated into (or directly uses) expression builder calls.

2. At runtime, calls to System.Linq.Queryable methods yield additional expression trees with argument expressions inline.

3. The provider is passed a LINQ expression which it translates into a “query” expression. LINQ to SQL and LINQ to Entities use different internal representations of the expression (a variant of LINQ expressions and Canonical Query Trees respectively). This step includes the replacement of method calls with query operators and the replacement of member accesses with store function calls.

4. Each provider then compensates for non-relational structures in the query (e.g. types, nested collections in results, etc.)

5. Native queries are generated and executed.

6. Query results are reshaped (basically the inverse of step 4).

As I mentioned, there is really nothing shared between LINQ to SQL and LINQ to Entities beyond step 2. The example in this thread illustrates a couple of differences between the two stacks in the handling of step 3 and step 4.

Implicit vs. explicit client evaluation

LINQ to SQL is a hybrid provider in the sense that it supports evaluation of parts of the query in the client and parts in the store. As a result, the following query succeeds in LINQ to SQL but fails in LINQ to Entities:

var query = from o in context.Orders

where GetCutoffDate() > o.OrderDate

select o;

As Brian suggested, it must be rewritten as:

DateTime cutoffDate = GetCutoffDate();

var query = from o in context.Orders

where cutoffDate > o.OrderDate

select o;

This makes the boundary between client and store evaluation explicit. There is a tradeoff between self-containment of queries and predictability of behavior for non-expert users.

Canonical functions vs. store functions

Of course, the sub-expression mentioned in this thread could be entirely translated into Transact-SQL function calls:

DateTime.UtcNow.AddDays(-180)

becomes

DATEADD(day, -180, GETUTCDATE())

Note that although LINQ to SQL could translate the above expression into Transact-SQL, it chooses to evaluate it on the client because it is uncorrelated. The behavior is different depending on whether results are correlated or not.

In Beta 2, LINQ to Entities does not support the DateTime.AddDays method simply because a corresponding “canonical function” does not exist. Canonical functions are store agnostic and can be implemented by arbitrary Entity Frameworks providers. We plan on introducing a few more DateTime-related functions in the next release (the usual disclaimers apply) at which point this expression will be supported by LINQ to Entities.

Regarding Rick’s question: Entity-SQL supports both canonical and store-specific functions. For functions not supported by LINQ to Entities, this provides the cleanest workaround. Where the gap is due to unsupported CLR methods – in either LINQ to SQL or LINQ to Entities – consider explicitly breaking up the query into client- and store- side elements. For instance, to extend the above example:

DateTime cutoffDate = GetCutoffDate();

var query = from o in context.Orders

where cutoffDate > o.OrderDate

select o;

var hybridQuery = from row in query.AsEnumerable()

select ShapeResult(row.Oid, row.Description, row.OrderDate);

Recommendation:

When working with LINQ to Entities, keep in mind that boundaries between client- and store- execution are explicit. To use a value computed on the client within a query, assign the value to a local variable before executing (see the assignment to cutoffDate above). To perform client-side processing of results, use the AsEnumerable method to yield results from the store query and then apply client-side logic (see the assignment to hybridQuery above).

Thanks,
-Colin

Enterprise Framework LINQ Queries failing - MSDN Forums

January 06

Make existing project a Volta project - MSDN Forums

 

Yes, this is possible, allthough you will need to modify the project file by hand. You can do this by right-clicking on the project and selecting'Unload project'. Next you will need to right-click on it again and select 'Edit ???.??proj'.

Then in the top-level propertygroup add the VoltaProjectKind, VoltaVersion and the ProjectTypeGuids elements.

Code Block

<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
     (....)

<VoltaProjectKind>WinformsApplication</VoltaProjectKind>

<VoltaVersion>1.0</VoltaVersion>

<ProjectTypeGuids></ProjectTypeGuids>

    (....)

</ProjectTypeGuids>

If it is a C# project insert:

{41daf090-9073-464d-9898-7bcdfc7d2642};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}

into the ProjectTypeGuids element. If it is a VB project insert:

{41daf090-9073-464d-9898-7bcdfc7d2642};{F184B08F-C81C-45F6-A57F-5ABD9991F28F}

The last thing to do is to replace:

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

or:

<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />

with:

<Import Project="$(VoltaInstallPath)\Microsoft.Volta.targets" />

This should do the trick. Please let us know if it doesn't.

Thanks,

Danny

Make existing project a Volta project - MSDN Forums

December 23

WinForms Tier-Splitting using Volta

 

I love the Volta idea and concept. The cool part is not the features, but lack of them.  It is so easy to create a two tier app it is almost not funny.

Here is a video I did on splitting using a Winforms app.  This uses Silverlight publishing so just double-click on the video to go full screen.

 

December 21

They are Anonymous Methods, not Anonymous Delegates.

 

It is not just a talking point because we want to be difficult. It helps us reason about what exactly is going on.  To be clear, there is *no such thing as an anonymous delegate. They don't exist (not yet).  They are "Anonymous Methods" - period.  It matters in how we think of them and how we talk about them.  Lets take a look at the anonymous method statement "delegate() {...}".  This is actually two different operations and when we think of it this way, we will never be confused again.  The first thing the compiler does is create the anonymous method under the covers using the inferred delegate signature as the method signature.  It is not correct to say the method is "unnamed" because it does have a name and the compiler assigns it. It is just hidden from normal view.  The next thing it does is create a delegate object of the required type to wrap the method. This is called delegate inference and can be the source of this confusion. For this to work, the compiler must be able to figure out (i.e. infer) what delegate type it will create. It has to be a known concrete type.  Let write some code to see why.

private void MyMethod()
{
}

Does not compile:

1) Delegate d = delegate() { };                       // Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type
2) Delegate d2 = MyMethod;                         // Cannot convert method group 'MyMethod' to non-delegate type 'System.Delegate'
3) Delegate d3 = (WaitCallback)MyMethod;   // No overload for 'MyMethod' matches delegate 'System.Threading.WaitCallback'

Line 1 does not compile because the compiler can not infer any delegate type. It can plainly see the signature we desire, but there is no concrete delegate type the compiler can see.  It could create an anonymous type of type delegate for us, but it does not work like that.  Line 2 does not compile for a similar reason. Even though the compiler knows the method signature, we are not giving it a delegate type and it is not just going to pick one that would happen to work (not what side effects that could have).  Line 3 does not work because we purposely mismatched the method signature with a delegate having a different signature (as WaitCallback takes and object).

Compiles:

4) Delegate d4 = (MethodInvoker)MyMethod;  // Works because we cast to a delegate type of the same signature.
5) Delegate d5 = (Action)delegate { };              // Works for same reason as d4.
6) Action d6 = MyMethod;                                // Delegate inference at work here. New Action delegate is created and assigned.

In contrast, these work. Line 1 works because we tell the compiler what delegate type to use and they match, so it works.  Line 5 works for the same reason. Note we used the special form of "delegate" without the parens. The compiler infers the method signature from the cast and creates the anonymous method with the same signature as the inferred delegate type. Line 6 works because the MyMethod() and Action use same signature.

I hope this helps.

Also see: http://msdn.microsoft.com/msdnmag/issues/04/05/C20/

December 20

Simple Task Scheduler inside your application (C#)

 

Many times I need a simple task scheduler inside a program to do this or that. You can use any of the system timers to achieve this, but you end up writing the same difficult code over and over. This simple scheduler is built to be simple and efficient. There is no interval "period" (i.e. system Timer) to worry about or set. If you need to reschedule a Task, just reschedule it at the end of your task delegate. That way, you don't have to worry about strange recursive overlaps. In a perfect world, I just would return a Task (in the pfx library), but you can't schedule a pfx.Task to run in the future. It is started during construction, so I could not return a Task. Instead I created something similar and named it TimerTask.

TimerScheduler is a static class that has 2 simple static methods - Add and Remove.  The Add() method will schedule a delegate (can use lambda syntax) at any point in the future and immediately return a TimerTask object to represent the task. The TimerTask can be canceled if it has not run yet. The Remove() method will un-schedule any task if it has not been started.  The scheduler works similar to System.Threading.Timer in that it adds Tasks to a list sorted by run times. Only one internal thread schedules tasks, each on a thread pool thread. The scheduler thread will block (i.e. do nothing) if no tasks are ready to run or the list is empty so it is efficient.  Any number of tasks can be scheduled to the limits of resources and max list size.  The only resources used for all waiting tasks is the object allocations and the single scheduler thread.

Hope it finds a way in a program or two.

--William

public static class TestTaskScheduler
{
    public static void Test1()
    {
        TimerTask tt = TaskScheduler.Add(DateTime.Now, () =>  Debug.WriteLine("Task1 done."));

        TimerTask tt2 = null;
        tt2 = TaskScheduler.Add(5000, () =>
        {
            Debug.WriteLine("Task2 done.");
            string ss = string.Format("Task:{0} RunDate:{1}", tt2.Completed, tt2.RunDate);
            Debug.WriteLine(ss);
        });
    }
}

public class TimerTask
{
    internal int completed;
    internal Exception exception;
    private readonly Action action;
    private readonly DateTime runDate;

    internal TimerTask(Action action, DateTime runDate)
    {
        this.action = action;
        this.runDate = runDate;
    }

    public bool Completed
    {
        get { return completed == 1; }
    }

    public DateTime RunDate
    {
        get { return this.runDate; }
    }

    public Exception Exception
    {
        get { return this.exception; }
    }

    public bool Cancel()
    {
        return TaskScheduler.Remove(this);
    }

    internal Action Action
    {
        get { return this.action; }
    }
}

/// <summary>
/// Schedules Tasks to run at future time.
/// </summary>
public static class TaskScheduler
{
    /// <summary>
    /// The maximum lag time allowed. RunAt times less then this value are not allowed.
    /// </summary>
    public static readonly TimeSpan MaxPassed;
    private static readonly object sync;
    private static Thread mt;
    private static SortedList<DateTime, TimerTask> sl;

    static TaskScheduler()
    {
        MaxPassed = TimeSpan.FromSeconds(-5);
        sync = new object();
        sl = new SortedList<DateTime, TimerTask>();
        mt = new Thread(Scheduler);
        mt.Name = "NewTimerScheduler";
        mt.IsBackground = true;
        mt.Start();
    }

    /// <summary>
    /// Schedule a Task to run at specified time.
    /// </summary>
    /// <param name="runAt"></param>
    /// <param name="action"></param>
    /// <returns></returns>
    public static TimerTask Add(TimeSpan runAt, Action action)
    {
        DateTime dt = DateTime.Now.Add(runAt);
        return Add(dt, action);
    }

    /// <summary>
    /// Schedule a Task to run at specified time.
    /// </summary>
    /// <param name="milliseconds"></param>
    /// <param name="action"></param>
    /// <returns></returns>
    public static TimerTask Add(double milliseconds, Action action)
    {
        DateTime dt = DateTime.Now.AddMilliseconds(milliseconds);
        return Add(dt, action);
    }

    /// <summary>
    /// Schedule a Task to run at specified time.
    /// </summary>
    /// <param name="runAt"></param>
    /// <param name="action"></param>
    /// <returns></returns>
    public static TimerTask Add(DateTime runAt, Action action)
    {
        if (action == null)
            throw new ArgumentNullException("action");
        if ((runAt - DateTime.Now) < MaxPassed)
            throw new InvalidOperationException("runAT is too far in the past.");

        TimerTask to = new TimerTask(action, runAt);

        lock (sync)
        {
            sl.Add(to.RunDate, to);
            Monitor.Pulse(sync);
            return to;
        }
    }

    /// <summary>
    /// Remove a TimerTask.
    /// </summary>
    /// <param name="timerTask">The TimerTask that was scheduled.</param>
    /// <returns>true if TimerTask has not been scheduled yet; otherwise false.</returns>
    public static bool Remove(TimerTask timerTask)
    {
        if (timerTask == null)
            throw new ArgumentNullException("timerTask");