Gunnar Peipman's ASP.NET blog

ASP.NET, C#, SharePoint, SQL Server and general software development topics.

Sponsors

News

 
 
 
DZone MVB

Links

Social

May 2011 - Posts

ASP.NET MVC: Showing dates using DayCalendarPage extension method

DayCalendarPageIn my events web site I need to show event dates in lists so users can easily see them. I decided to use day calendar view like shown on image on left. As there are more than one view where I need this functionality I wrote HTML extension method that outputs day calendar view based on current date. In this posting I will show you my extension method and show you how to use it.

DayCalendarPage extension method

Here is the extension method that generates day calendar page like shown above.


public static MvcHtmlString DayCalendarPage(this HtmlHelper helper, DateTime date)

{

    var buffer = new StringBuilder();

    buffer.Append(@"<div class=""dayCalendarPage"">");

 

    buffer.Append(@"    <div class=""title"">");

    buffer.Append(date.ToString("MMM"));

    buffer.Append(@"    </div>");

 

    buffer.Append(@"    <div class=""day"">");

    buffer.Append(date.ToString("dd"));

    buffer.Append(@"    </div>");

 

    buffer.Append(@"</div>");

 

    return MvcHtmlString.Create(buffer.ToString());

}


This method outputs HTML that is made to nice day calendar page using CSS.

CSS

Here is my CSS that makes calendar look nice. It is not very optimal I think but it works.


/* DAY CALENDAR PAGE */
.dayCalendarPage
{
    
clear:none
;
    
float:left
;
    
text-align:center

    
border:1px solid lightgrey

    
margin-right:10px
;
}
.dayCalendarPage .title
{
    
background-color:Red
;
    
color:White
;
    
width:50px
;    
}
.dayCalendarPage .day
{
     font-size:15pt;
    
font-weight:bold
;
    
padding-top: 5px
;
    
padding-bottom: 5px;
}

Now as you have extension method and styles added to your project it is time to use them.

How to use DayCalendarPage method

Here is the example about how to use DayCalendarPage extension method.


@foreach (var item in Model.Results) {
    
<tr>
        <td colspan="10">
           @Html.DayCalendarPage(item.StartDate)
          
<div>
              @Html.ActionLink(item.Title,"event", new { id = item.Id})
              <
br />
              @item.Description
           </div>
       </td>
    </tr>
}

Now it’s time to see the output.

Result

Here’s my test result. This data is arbitrary and please don’t take dates here seriously.

DayCalendarPage extension method in action

Feel free to use this code in your projects if you like it.

Using DebugView to catch debug output of .NET program

DebugViewOften asked question: is there any way to gather debug output of .NET program that is running on environment where Visual Studio is not installed? Yes, you can do it and you can do it for free with program called DebugView. Here’s how it works.

After downloading and unzipping DebugView you can run it and select debug output options. I suggest you to run it as Administrator because otherwise it may state that there is already debugger up and running when you try to check Capture Global Win32 option.

DebugView: Capture options

DebugView starts listening immediately. As a next thing I will write some debug information to my code. This is one of my action methods in very early state and it’s safe to play with it.


public ActionResult Index(int page = 1)

{

    Debug.WriteLine("HomeController.Index: started, page=" + page);

 

    PagedResult<Event> events;

 

    using (var model = new EventsEntities())

    {

        events = model.ListPublicEvents(page);

    }

 

    Debug.WriteLine("HomeController.Index: finished");

    return View(events);

}


Now let’s run the code and see what DebugView is able to catch. Don’t run the code through Visual Studio as it attaches its own debugger and DebugView is not able to catch the output then.

DebugView: Debug output

Besides log messages you can also see how much time it takes to move from one debug output to another. If you have lengthy output then you can also use find functionality to search for specific log messages.

Posted: May 20 2011, 06:48 AM by DigiMortal | with 6 comment(s)
Filed under: ,
dotPeek–JetBrains replaces .NET Reflector

Today I got e-mail from JetBrains stating that there is dotPeek early build available for download. dotPeek is .NET assemblies decompiler that is offered for free and that should replace .NET Reflector (not free anymore). dotPeek will also be part of ReSharper 6. In this posting I will give you brief introduction about dotPeek.

dotPeek in pictures

Here you can see dotPeek showing contents of DataRow class.

dotPeek: Source code of DataRow class

dotPeek is able to get sources from symbol files and decompiling the assembly.

dotPeek: Decompile sources or get sources from symbol files

Symbol files are downloaded from Microsoft reference sources server.

dotPeek: Downloading symbol files from MS server

One very cool feature I found is that you can search for class usages in loaded assemblies.

dotPeek: Find usages of class in assemblies

Results are shown in separate pane and you can click nodes open to see where class is used.

My experience

dotPeek works smoothly and fine once it is loaded. UI is responsive and works fine. Although this is early version it is worth to try out because quality is high as always when JetBrain releases something. Some downsides I mentioned:

  • event for small amount assemblies (the ones shown by deafult) the memory consumption is about 150MB,
  • decompiling of classes seems to be slower than in .NET Reflector,
  • UI doesn’t let you know when it works on something (no notice on statusbar).

I think these problems will be solved when dotPeek is ready.

Conclusion

Making .NET Reflector paid product means that glory days of .NET Reflector are over. Competitors with very good skills are developing alternative free tools and I’m almost sure that .NET Reflector has no way back. dotPeek is very good example of market changes. There are nice new features like symbol stores support and I am sure that based on ReSharper experiences there will be more nice features that we will find from dotPeek in near future.

Posted: May 19 2011, 01:32 AM by DigiMortal | with 5 comment(s)
Filed under: ,
Using Advantage data providers to read DBF-files

In one of my projects I have to read FoxPro DBF-files and import data from them. As this code must run in server and customer doesn’t want to install FoxPro there we found another solution that seems at least to me way better. In this posting I will show you how to read DBF-files using Sybase Advantage data providers.

Getting Advantage data providers

Here are the download links to data providers:

I downloaded and installed .NET data provider and my example here is fully based on this.

Configuring application

Advantage Data provider test applicationIf you run application without configuring some data providers stuff before you will get the following error:

Error 5185: Local server connections are restricted in this environment. See the 5185 error code documentation for details.

Go to your application bin folder and add there usual text file called ads.ini. Here is the content for this file:

[SETTINGS]
MTIER_LOCAL_CONNECTIONS=1

Make sure you add reference to Advantage data provider assembly and include ads.ini to your project like shown on image above.

Getting data to DataTable

Here is short code example about how to get data from DBF-file to DataTable.


static void Main(string[] args)

{

    var tableName = "TABLENAME_WITHOUT_EXTENSION";

 

    var connStr = "data source={0};tabletype=vfp;servertype= local;";

    connStr = string.Format(connStr, "c:\\temp\\");

 

    var table = new DataTable();

 

    using (var conn = new AdsConnection(connStr))           

    using (var adapter = new AdsDataAdapter())

    using (var cmd = new AdsCommand())

    {

        cmd.Connection = conn;

        cmd.CommandText = "select * from " + tableName;

        adapter.SelectCommand = cmd;

 

        conn.Open();

        adapter.Fill(table);

        conn.Close();

    }
 

    Console.WriteLine("Table fields:");

    foreach (DataColumn col in table.Columns)

        Console.WriteLine(col.ColumnName);

 

    Console.WriteLine(" ");

    Console.WriteLine("Rows: " + table.Rows.Count);

 

    Console.Read();

}


If Advantage data providers were installed correctly and there are no errors in table names, locations and your SQL query then you should see list of table column names and row count on console window when you run the application.

Posted: May 16 2011, 01:41 AM by DigiMortal | with 1 comment(s)
Filed under: ,
Timepicker–nice extension to jQuery UI Datepicker

jQuery UI Datepicker is popular dropdown calendar component. It is powerful, easy to use and one of my favorites for sure. Sometimes we need more than just picking dates. In one of my projects I needed something similar but instead of just dates I had dates and times. As I’m not strong on jQuery I looked for ready made component to get this functionality and then how I found Timepicker extension for jQuery UI Datepciker. Here’s how it looks and how to use it.

Timepicker needs jQuery UI Datepicker and sliders to work. This is how Timepicker looks in action.

jQuery Timepicker in action

And here is the code I use to include it to my view.


<style type="text/css">
/* css for timepicker */
.ui-timepicker-div .ui-widget-header{ margin-bottom: 8px
; }
.ui-timepicker-div dl{ text-align: left
; }
.ui-timepicker-div dl dt{ height: 25px
; }
.ui-timepicker-div dl dd{ margin: -25px 0 10px 65px
; }
.ui-timepicker-div td { font-size: 90%
; }
</style>
    
<script src="@Url.Content("~/Scripts/jquery-ui-timepicker-addon.js")" type="text/javascript"></script>
 
<script type="text/javascript">
    $(function
()
    {        
         $(
"#StartDate"
).datetimepicker();
         $(
"#EndDate"
).datetimepicker();        
         $(
"#PublishDate"
).datetimepicker();    
    });
</script
>

Is it easy to use for users in real situations? Yes, it is. I tried it on myself. To get answer I tried to insert about 10 pieces of data using view that incorporates Timepicker component and I was happy with it.

If you like Timepicker component then here are the links:

ASP.NET MVC: Getting selected values from CheckBoxList
 

In my last posting I introduced how to implement CheckBoxList in ASP.NET MVC. Showing checkbox list is one part of the story. When user saves the form then we have to update also data that was represented by CheckBoxList. In this posting I will show you how to update event tags collection when user saves event.

Prerequisites

To get better idea what I’m doing and what is the system and code I am working on take a quick look at these blog posts I wrote previously:

I think these two postings will give you enough background even if you just go quickly through them.

Getting tags back from controller

CheckBoxList extension method did already something right – it outputs tags as checkboxes with same name. Now it is really up to MVC to catch the result and to transform it to something we can use. And MVC does it pretty well as we see from the following code.


[HttpPost]

public ActionResult Edit(Event evt, int[] tagIds)

{

    // ...

}


Yes, we will get back ID-s of selected tags to tagIds array if we name our checkbox list as tagIds. Here the example call to CheckBoxList() method in my view.

@Html.Raw(Html.CheckBoxList("tagIds", Model.TagsSelection));

Updating tags collection

Now we have selected tag ID-s and it’s time to update event tags collection. If you think that you just clear the tags collection and add new set of tags there then you are wrong. Don’t forget that our objects are persisted by Entity Framework (or by some other mapper) and they track the state of object and its members.

To avoid non-necessary deletes and inserts we have to synchronize current tag set of event with new one that came from form. It really doesn’t matter in my case as my site will be small. Here’s the code that synchronizes tags (deletes tags that were not selected and adds the ones that user selected).


private void SetEventTags(Event evt, int[] tagIds)

{

    var selectedTags = GetTagsByIds(tagIds);

 

    var eventTags = evt.Tags.ToList();

    foreach (var tag in eventTags)

        if (!selectedTags.Contains(tag))

            evt.Tags.Remove(tag);

 

    foreach (var tag in selectedTags)

        if (!eventTags.Contains(tag))

            evt.Tags.Add(tag);

}

 

private IList<Tag> GetTagsByIds(int[] tagIds)

{

    var selectedTags = new List<Tag>();

 

    foreach (var tagId in tagIds)

    {

        var tag = db.Tags.Single(t => t.Id == tagId);

        selectedTags.Add(tag);

    }

 

    return selectedTags;

}


And here’s the example of our controller action.


[HttpPost]

public ActionResult Edit(Event evt, int[] tagIds)

{

    // ...

 

    db.events.Attach(evt);

    SetEventTags(evt, tagIds);

 

    db.ObjectStateManager.ChangeObjectState(evt, EntityState.Modified);

    db.SaveChanges();
 

    return RedirectToAction("Index");

}


Conclusion

Now you know how to implement checkbox list in ASP.NET MVC and how to get data back from list. We saw that getting tags back from checkbox list was very easy. We just names checkbox list like parameter of save method and ASP.NET MVC was able to build tag ID-s array for us. We also saw how to add selected tags to event tags collection without deleting all tags and then adding selected ones back.

ASP.NET MVC: Implementing CheckBoxList
 

My events site I’m building ASP.NET MVC got tags support for events. I implemented CheckBoxList helper method and tag updater method that I can use to update tags assigned to events. In this posting I will show you how to implement tags support using CheckBoxList helper in ASP.NET MVC.

About my solution

My model: events and tagsMy event and tag object are shown on image on right. It’s the same system I used as example in my blog posting about implementing tagging support in ASP.NET MVC applications. Between events and tags there is many-to-many relationship. Because table between events and tags has composite primary key that is made of event ID and tag ID (no more fields) it is not mapped as object by Entity Framework but as many-to-many relationship between events and tags.

My admin interface is right now generated by using controllers scaffolding with Entity Framework data model. It is simple, minimal and primitive (and a little bit disturbing). I needed a way to assign tags to events through admin interface. On ASP.NET Forms we have checkbox list available. In MVC we have nothing built-in. So I implemented something using materials I found form web.

Implementing CheckBoxList

As a first thing let’s make CheckBoxList work. There is very good solution offered by Jeremiah Clark in his blog posting CheckBoxList Helper for MVC. I have a little bit modified version of it – partly written and before and partly after I found Jeremiah’s solution. I will polish it later if I have tried this extension method on more than one entity tagging form.


public static string CheckBoxList(this HtmlHelper helper, string name, IEnumerable<SelectListItem> items)

{

    var output = new StringBuilder();

    output.Append(@"<div class=""checkboxList"">");

 

    foreach (var item in items)

    {

        output.Append(@"<input type=""checkbox"" name=""");

        output.Append(name);

        output.Append("\" value=\"");

        output.Append(item.Value);

        output.Append("\"");

 

        if (item.Selected)

            output.Append(@" checked=""chekced""");

 

        output.Append(" />");

        output.Append(item.Text);

        output.Append("<br />");

    }

 

    output.Append("</div>");

 

    return output.ToString();

}


That’s nice but how I display tags list with selected tags?

Creating tags list

As a next thing we have to create tag list that we can show on event creating and editing forms. Having event tags list and all tags list is not enough for us. We have to create list of SelectListItem objects and give it to our view. Here is my implementation of method that returns me appropriate SelectItemList list that is based on event and tags data.


private IEnumerable<SelectListItem> GetEventTagsSelection(Event evt, IEnumerable<Tag> tags)

{

    var result = new List<SelectListItem>();

 

    foreach (var tag in tags)

    {

        var item = new SelectListItem

        {

            Text = tag.Title,

            Value = tag.Id.ToString(),

            Selected = evt.Tags.Contains(tag)

        };

 

        result.Add(item);

    }

 

    return result;

}


GetEventsTagSelection() method accepts event and all tags list. Based on this information it creates list of all tags and selects the ones that belong to event. Here is the example of checkbox list generated by CheckBoxList() extension method.

ASP.NET MVC: Output of CheckBoxList

So, seems like real. In my next posting about CheckBoxList I will show you how to update tags in controller action that is used to save event data.

Conclusion

Extending ASP.NET MVC views by custom helper methods is easy and straightforward. As we saw it was not complex task to create checkbox list method that outputs fully functional list of check boxes. One annoying thing was that we had to create method that converted tags to SelectListItem objects but it was still nothing complex. In next posting I will show you how to update event tags that were posted back from form with checkbox list.

ASP.NET MVC: How to implement invitation codes support
 

Last Christmas I blogged about how to make ASP.NET MVC users authorized only if they have profiles created. This works well on public sites where everybody can be user. Sometimes we don’t want to let all users to our system even when they were correctly authenticated by some authentication service. In this blog post I will show you how to create authorization attribute that you can use to make authenticated users insert their access code if it is their first visit to site.

About my solution

In my application users are authenticated through AppFabric Access Control Service using Windows Live ID. This means that for every authenticated user I will get only authentication token back from Windows Live ID.

Okay, I can show it to users and tell them to e-mail it to me and then insert their data manually but this makes my solution weird. What I can do is add support for invitation codes to my site. Then I can add users I expect to join and send them invitation codes that I also add to users table. When user logs in I will check if he or she has account in system and if there’s no account then system asks for invitation code.

User class

aspnet-mvc-invitation-code-user-classHere is the example of my User class. It is simple and small because I don’t need any advanced profiles stuff in my system. There are two important fields:

  • AccessCode – GUID that is used as invitation code. This attribute is unique and it is required for all users who access the system. That’s why it was also very good candidate for primary key.
  • UserToken – this field holds unique token for user. This token is coming from Live ID service and it is assigned to user when user inserts correct access code.

So, as a first thing I will insert new accounts to users table and then I will send out invitation codes to users. After successful authentication user is asked for invitation code and if user inserts correct invitation code then his or her Live ID token is inserted to users table row that is identified by given access code.

AccessCodeAuthorizationAttribute

I will use controller attribute on admin interface controllers to restrict access to administrative features. Here is the code for this attribute class.


public class AccessCodeAuthorizationAttribute : AuthorizeAttribute

{

    public override void OnAuthorization(AuthorizationContext filterContext)

    {

        base.OnAuthorization(filterContext);

 

        var httpContext = filterContext.HttpContext;

        var identity = httpContext.User.Identity;

 

        using(var ctx = new EventsEntities())

        {

            var user = ctx.GetUserByToken(identity.GetUserToken());

            if(user != null)

            {

                httpContext.Session["UserId"] = user.AccessCode;

                return;

            }

        }

 

        if (!identity.IsAuthenticated ||
            httpContext.Session[
"UserId"] == null)

            if (filterContext.Result == null)

                    httpContext.Response.Redirect("~/getaccess");

    }

}


EventsEntities is my Entity Framework model class. GetUserByToken() method looks for user with given security token (actually it is the value of name identifier claim).

GetUserToken() is extension method to IIdentity and it returns us unique code that Live ID service gives to user in our system context (you can use other authentication providers through AppFabric Access Control Services too). As I am using claims based authentication I need something to find the value of name identifier claim.


public static string GetUserToken(this IIdentity identity)

{

    var claimsIdentity = (ClaimsIdentity) identity;

    var nameClaimQuery = from c in claimsIdentity.Claims

                         where c.ClaimType == ClaimTypes.NameIdentifier

                         select c;

    var nameClaim = nameClaimQuery.FirstOrDefault();

    if(nameClaim == null)

        return string.Empty;

 

    return nameClaim.Value;

}


And here is how this attribute is used with administrator area home controller.


[AccessCodeAuthorization]

public class AdminHomeController : Controller

{

    public ActionResult Index()

    {

        return View();

    }

}


In this point you can try to run the code and request admin interface through browser. If there is no errors you will be redirected to /getaccess page.

Asking invitation code

Now let’s create new view – GetAccess – that is used to ask invitation code from user. Here is the markup of this view.


@{    
    ViewBag.Title =
"Insert invitation code"
;
}

<h2>Insert invitation code</h2>

@Html.ValidationMessage("accessCode"
)

@
using
(Html.BeginForm()) {     <span
        Invitation code:
        @Html.TextBox(
"accessCode"
        <input type="submit" value="Ok" />
    </
span>
}

The page looks something like this.

aspnet-mvc-insert-invitation-code

And here are controller methods for displaying and saving invitation code. I use GUID-s as invitation codes. This code needs optimization and refactoring but it works also like it is right now.


[HttpGet]

public ActionResult GetAccess()

{

    return View();

}

 

[HttpPost]

public ActionResult GetAccess(string accessCode)

{

    if(string.IsNullOrEmpty(accessCode.Trim()))

    {

        ModelState.AddModelError("accessCode", "Insert invitation code!");

        return View();

    }

 

    Guid accessGuid;

 

    try

    {

        accessGuid = Guid.Parse(accessCode);

    }

    catch

    {

        ModelState.AddModelError("accessCode", "Incorrect format of invitation code!");

        return View();               

    }

 

    using(var ctx = new EventsEntities())

    {

        var user = ctx.GetNewUserByAccessCode(accessGuid);

        if(user == null)

        {

            ModelState.AddModelError("accessCode", "Cannot find account with given invitation code!");

            return View();

        }

 

        user.UserToken = User.Identity.GetUserToken();

        ctx.SaveChanges();

    }

 

    Session["UserId"] = accessGuid;

 

    return Redirect("~/admin");

}


When user inserts invitation code and clicks OK the invitation code is validated. If the code is valid then we ask User with given invitation code from database. Of course, we have one additional check needed – if code is already taken we have to return null from GetNewUserByAccessCode() method. If user inserts free invitation code then this user account is bound to current user and next time when he or she logs in the invitation code is not asked anymore.

Conclusion

As you saw it was not complex task to add support for invitation codes to system. We created new authorization attribute that checks if authenticated user has account or not and if there is no account for user in our system we will ask invitation code from user. To avoid keeping user names and passwords in our system and therefore open it to different kind of nasty attacks we used Windows Azure AppFabric ACS services to authenticate users through Windows Live ID.

More Posts