Dynamic is magic : A solution to use the ASP.NET profile in web applications.

Posted January 31st, 2012 in ASP.NET, HowTo, Tips and Tricks, Web development by admin

Profiles are not auto generated with Web Applications, so you can’t just add them in the web.config and use them directly. (unless …)

The WebSite project do a magic thing : when you add properties to the profile in the web.config file, a class is autogenerated and allow the developer to access these properties. The web application project don’t do that.

You can find some workarounds over the web, here is some

The “dynamic” keyword help us here.

So, no more chit chat, here is the code snippets for a profile with 3 parameters : LastName, FirstName and GSM

web.config:


<profile enabled="true">
 <providers>
 <clear/>
 <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="MyApp"/>
 </providers>
 <properties>
 <add name="FirstName" type="string"/>
 <add name="LastName" type="string"/>
 <add name="GSM" type="string"/>
 </properties>
 </profile>

A “business” class, I called it “ProfilePresenter”, it returns the profile of the logged user and allow modifications:


public class ProfilePresenter
{
 public dynamic GetProfile()
 {
 return HttpContext.Current.Profile;
 }
 public dynamic UpdateProfile(string FirstName, string LastName, string GSM)
 {
 HttpContext.Current.Profile.SetPropertyValue("FirstName", FirstName);
 HttpContext.Current.Profile.SetPropertyValue("LastName", LastName);
 HttpContext.Current.Profile.SetPropertyValue("GSM", GSM);
 HttpContext.Current.Profile.Save();
 return HttpContext.Current.Profile;
 }
}

A page that uses the ProfilePresenter class : displaying the profile properties, and edit them

ObjectDataSource:


<asp:ObjectDataSource runat="server" ID="ProfileODS" TypeName="Board.Presenters.ProfilePresenter"
 SelectMethod="GetProfile" UpdateMethod="UpdateProfile"/>
<pre>

FormView: Display part

 <asp:FormView runat="server" ID="ProfileFV" DataSourceID="ProfileODS" RenderOuterTable="false">
 <EmptyDataTemplate>
 <p>
 No profil datas
 </p>
 </EmptyDataTemplate>
 <ItemTemplate>
 <h2>
 Profil informations</h2>
 <div>
 <asp:Button runat="server" ID="Edit" CommandName="Edit" Text="Edit" /></div>
 <table>
 <thead>
 <tr>
 <th colspan="2">
 Infos
 </th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <th>
 LastName
 </th>
 <td>
 <%# Eval("LastName")%>
 </td>
 </tr>
 <tr>
 <th>
 FirstName
 </th>
 <td>
 <%# Eval("FirstName")%>
 </td>
 </tr>
 <tr>
 <th>
 GSM
 </th>
 <td>
 <%# Eval("GSM")%>
 </td>
 </tr>
 </tbody>
 </table>
 </ItemTemplate>

FormView : the Edit part

 <EditItemTemplate>
 <h2>
 Profil Update</h2>
 <div>
 <asp:Button runat="server" ID="Edit" CommandName="Cancel" Text="Annuler" />
 <asp:Button runat="server" ID="Button1" CommandName="Update" Text="Sauver" /></div>
 <table>
 <thead>
 <tr>
 <th colspan="2">
Infos
 </th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <th>
 LastName
 </th>
 <td>
 <asp:TextBox runat="server" ID="LastName" Text='<%# Bind("LastName")%>' />
 </td>
 </tr>
 <tr>
 <th>
 FirstName
 </th>
 <td>
 <asp:TextBox runat="server" ID="FirstName" Text='<%# Bind("FirstName")%>' />
 </td>
 </tr>
 <tr>
 <th>
 GSM
 </th>
 <td>
 <asp:TextBox runat="server" ID="GSM" Text='<%# Bind("GSM")%>' />
 </td>
 </tr>
 </tbody>
 </table>
 </EditItemTemplate>
 </asp:FormView>

A simple use :


dynamic profil = HttpContext.Current.Profile;
if (profil != null)
{
 Console.Writeline(profil.GSM);
}

Another example : retrieve the gsm numbers from  members of a security role. It shows how to retrieve the profile of an other user


string[] users = Roles.GetUsersInRole(role);

List<string> gsm = new List<string>();
foreach (string user in users)
{
 dynamic profil = HttpContext.Current.Profile;
 dynamic profi = profil.GetProfile(user);
 if (profi != null)
 {
 if (!string.IsNullOrEmpty(profi.GSM))
 {
 gsm.Add(profi.GSM);
 }
 }
}

Let me know what you think !

Different Ways to Transfer Data between pages by Peter Bromberg

Posted December 30th, 2011 in ASP.NET by admin

It’s a common question when working with asp.net, and Peter Bromberg has done a nice job by grouping eight methods to do it!

Read his article here : http://www.eggheadcafe.com/tutorials/asp-net/e653f028-01fb-4d0e-843b-058deae562a2/eight-different-ways-to-transfer-data-from-one-page-to-another-page.aspx

Bring a bit of the Subsonic power to Entity Framework by adding automatic audit and logical delete fields

Posted November 4th, 2011 in .NET, ADO.NET, Productivity, SubSonic, Uncategorized by admin

Here is the code to do the same thing than in my previous article “Bring a bit of the Subsonic power to Linq to sql by adding automatic audit and logical delete fields”


namespace YouNamespace.DAL
{
 using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Data;
 using System.Data.Common;
 using System.Data.Objects;
 using System.Linq;

 public partial class YOURCONTEXTEntities
 {
 /// <summary>
 /// System fields for automatic audit and logical delete
 /// </summary>
 private struct SystemFields
 {
 public const string CreatedOn = "CREATEDON";
 public const string ModifiedOn = "MODIFIEDON";
 public const string CreatedBy = "CREATEDBY";
 public const string ModifiedBy = "MODIFIEDBY";
 public const string IsDeleted = "ISDELETED";
 }

 /// <summary>
 /// Overriding the SaveChanges method to automaticaly set system fields if any.
 /// </summary>
 /// <param name="options"></param>
 /// <returns></returns>
 public override int SaveChanges(System.Data.Objects.SaveOptions options)
 {
 IEnumerable<ObjectStateEntry> newEntries = this.ObjectStateManager.GetObjectStateEntries(EntityState.Added);

 foreach (ObjectStateEntry entry in newEntries)
 {
 ReadOnlyCollection<FieldMetadata> fieldsMetaData = entry.CurrentValues
 .DataRecordInfo.FieldMetadata;

 FieldMetadata createdOnField = fieldsMetaData
 .Where(f => string.Equals(f.FieldType.Name, SystemFields.CreatedOn, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (createdOnField.FieldType != null)
 {
 entry.CurrentValues.SetValue(createdOnField.Ordinal, DateTime.Now);
 }

 FieldMetadata createdByField = fieldsMetaData
 .Where(f => string.Equals(f.FieldType.Name, SystemFields.CreatedBy, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (createdByField.FieldType != null)
 {
 entry.CurrentValues.SetValue(createdByField.Ordinal, "Sam");
 }

 FieldMetadata deletedField = fieldsMetaData
 .Where(f => string.Equals(f.FieldType.Name, SystemFields.IsDeleted, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (deletedField.FieldType != null)
 {
 entry.CurrentValues.SetValue(deletedField.Ordinal, false);
 }
 }

 IEnumerable<ObjectStateEntry> modifiedEntries = this.ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
 foreach (ObjectStateEntry entry in modifiedEntries)
 {
 ReadOnlyCollection<FieldMetadata> fieldsMetaData = entry.CurrentValues
 .DataRecordInfo.FieldMetadata;

 FieldMetadata createdOnField = fieldsMetaData
 .Where(f => string.Equals(f.FieldType.Name, SystemFields.ModifiedOn, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (createdOnField.FieldType != null)
 {
 entry.CurrentValues.SetValue(createdOnField.Ordinal, DateTime.Now);
 }

 FieldMetadata createdByField = fieldsMetaData
 .Where(f => string.Equals(f.FieldType.Name, SystemFields.ModifiedBy, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (createdByField.FieldType != null)
 {
 entry.CurrentValues.SetValue(createdByField.Ordinal, "Sam");
 }
 }

 IEnumerable<ObjectStateEntry> deletedEntries = this.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted);
 foreach (ObjectStateEntry entry in deletedEntries)
 {
 // change from deleted to modified (!important)
 this.ObjectStateManager.ChangeObjectState(entry.Entity, EntityState.Modified);

 ReadOnlyCollection<FieldMetadata> fieldsMetaData = entry.CurrentValues
 .DataRecordInfo.FieldMetadata;

 FieldMetadata deletedField = fieldsMetaData
 .Where(f => string.Equals(f.FieldType.Name, SystemFields.IsDeleted, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

 if (deletedField.FieldType != null)
 {
 entry.CurrentValues.SetValue(deletedField.Ordinal, true);
 }
else
 {
 // change back from modified to deleted (!important)
 this.ObjectStateManager.ChangeObjectState(entry.Entity, EntityState.Deleted);
 }
 }

 return base.SaveChanges(options);
 }
 }
}

Enum HasFlag method extension for < 4.0 Framework

Posted August 3rd, 2011 in .NET by admin

In the same idea than the previous article, here is an extension method to mimic the 4.0 HasFlag method (http://msdn.microsoft.com/en-us/library/system.enum.hasflag.aspx).

     /// <summary>
    /// Extentions for enums.
    /// </summary>
    public static class EnumExtensions
    {
        /// <summary>
        /// A FX 3.5 way to mimic the FX4 "HasFlag" method.
        /// </summary>
        /// <param name="variable">The tested enum.</param>
        /// <param name="value">The value to test.</param>
        /// <returns>True if the flag is set. Otherwise false.</returns>
        public static bool HasFlag(this Enum variable, Enum value)
        {
            // check if from the same type.
            if (variable.GetType() != value.GetType())
            {
                throw new ArgumentException("The checked flag is not from the same type as the checked variable.");
            }

            Convert.ToUInt64(value);
            ulong num = Convert.ToUInt64(value);
            ulong num2 = Convert.ToUInt64(variable);

            return (num2 & num) == num;
        }
    }

Stream.CopyTo method for < 4.0 framework

Posted August 2nd, 2011 in .NET by Sam Beauvois

The .NET Framework 4.0 introduced the CopyTo() method for the Stream class. (http://msdn.microsoft.com/en-us/library/system.io.stream.copyto.aspx)

You copy a stream into one other this way:


   MemoryStream memoryStream = new MemoryStream();
   using (Stream stream = new FileStream(@"c:\input.txt", FileMode.Open))
   {
      stream.CopyTo(memoryStream);
   }

If you are stucked with a lower version of the framework, you might want to use it anyway.

A bit of reflector is realy usefull to see how the implementation is done in 4.0.

The CopyTo method :


public void CopyTo(Stream destination)
{
    if (destination == null)
    {
        throw new ArgumentNullException("destination");
    }
    if (!this.CanRead && !this.CanWrite)
    {
        throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_StreamClosed"));
    }
    if (!destination.CanRead && !destination.CanWrite)
    {
        throw new ObjectDisposedException("destination", Environment.GetResourceString("ObjectDisposed_StreamClosed"));
    }
    if (!this.CanRead)
    {
        throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnreadableStream"));
    }
    if (!destination.CanWrite)
    {
        throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnwritableStream"));
    }
    this.InternalCopyTo(destination, 0x1000);
}

We see that the InternalCopyTo is used :


private void InternalCopyTo(Stream destination, int bufferSize)
{
    int num;
    byte[] buffer = new byte[bufferSize];
    while ((num = this.Read(buffer, 0, buffer.Length)) != 0)
    {
        destination.Write(buffer, 0, num);
    }
}

Remark :
0×1000 is in hexadecimal, which corresponds to 4096 in decimal.

So we can retrieve that for use with lower versions of the language

For .NET FX >= 3.0 you can create an extension method


    using System;
    using System.IO;

    /// <summary>
    /// Extension methods for streams.
    /// </summary>
    public static class StreamExtensions
    {
        /// <summary>
        /// Reads all the bytes from the current stream and writes them to the destination stream.
        /// </summary>
        /// <param name="original">The current stream.</param>
        /// <param name="destination">The stream that will contain the contents of the current stream.</param>
        /// <exception cref="System.ArgumentNullException">Destination is null.</exception>
        /// <exception cref="System.NotSupportedException">The current stream does not support reading.-or-destination does not support Writing.</exception>
        /// <exception cref="System.ObjectDisposedException">Either the current stream or destination were closed before the System.IO.Stream.CopyTo(System.IO.Stream) method was called.</exception>
        /// <exception cref="System.IO.IOException">An I/O error occurred.</exception>
        public static void CopyTo(this Stream original, Stream destination)
        {
            if (destination == null)
            {
                throw new ArgumentNullException("destination");
            }
            if (!original.CanRead && !original.CanWrite)
            {
                throw new ObjectDisposedException("ObjectDisposedException");
            }
            if (!destination.CanRead && !destination.CanWrite)
            {
                throw new ObjectDisposedException("ObjectDisposedException");
            }
            if (!original.CanRead)
            {
                throw new NotSupportedException("NotSupportedException source");
            }
            if (!destination.CanWrite)
            {
                throw new NotSupportedException("NotSupportedException destination");
            }

            byte[] array = new byte[4096];
            int count;
            while ((count = original.Read(array, 0, array.Length)) != 0)
            {
                destination.Write(array, 0, count);
            }
        }
    }

You use it this way (same ways as the FX 4.0):


   MemoryStream memoryStream = new MemoryStream();
   using (Stream stream = new FileStream(@"c:\input.txt", FileMode.Open))
   {
      stream.CopyTo(memoryStream);
   }

For lower version, you can create an helper class.


    using System;
    using System.IO;

    /// <summary>
    /// An helper class for streams.
    /// </summary>
    public class StreamHelper
    {
        /// <summary>
        /// Reads all the bytes from the current stream and writes them to the destination stream.
        /// </summary>
        /// <param name="original">The original stream.</param>
        /// <param name="destination">The stream that will contain the contents of the current stream.</param>
        /// <exception cref="System.ArgumentNullException">Destination is null.</exception>
        /// <exception cref="System.NotSupportedException">The current stream does not support reading.-or-destination does not support Writing.</exception>
        /// <exception cref="System.ObjectDisposedException">Either the current stream or destination were closed before the System.IO.Stream.CopyTo(System.IO.Stream) method was called.</exception>
        /// <exception cref="System.IO.IOException">An I/O error occurred.</exception>
        public static void CopyStreamTo(Stream original, Stream destination)
        {
            if (destination == null)
            {
                throw new ArgumentNullException("destination");
            }
            if (!original.CanRead && !original.CanWrite)
            {
                throw new ObjectDisposedException("ObjectDisposedException");
            }
            if (!destination.CanRead && !destination.CanWrite)
            {
                throw new ObjectDisposedException("ObjectDisposedException");
            }
            if (!original.CanRead)
            {
                throw new NotSupportedException("NotSupportedException source");
            }
            if (!destination.CanWrite)
            {
                throw new NotSupportedException("NotSupportedException destination");
            }

            byte[] array = new byte[4096];
            int count;
            while ((count = original.Read(array, 0, array.Length)) != 0)
            {
                destination.Write(array, 0, count);
            }
        }
    }

Use it this way:


   MemoryStream memoryStream = new MemoryStream();
   using (Stream stream = new FileStream(@"c:\input.txt", FileMode.Open))
   {
        StreamHelper.CopyStreamTo(stream, memoryStream);
   }