Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Sunday, April 17, 2011

A mystery solved

Today, I was trying to solve a problem where on our French site, a specification number (which is a decimal number) of the same product  was toggling between 1.3 and 1,3 intermittently.  It should be 1,3 for French.  It turned out the problem was in two folds.


First of all, the following code is being used to convert decimal to string:
//specNumber = 1.3;
specNumber.ToString();


Secondly, the app is running on two load balanced servers.  One server's region and language is set up as:

 while the other is set up as below:

That explains why the value is appearing as 1.3 or 1,3 intermittently.


To address this problem, we need to fix it in code.  When the site is being browsed in French we'll use:

   var fr = CultureInfo.CreateSpecificCulture("fr-CA");
   specNumber.ToString(fr.NumberFormat);

That way, the code is not dependent on the server region and language settings.

Tuesday, April 12, 2011

Custom Routing in MVC

In MVC, by default, out of the box routing pattern is {controller}/{action}/{id} where id is optional as defined in the Global.asax.cs:

            routes.MapRoute
                (
                    "Default"// Route name
                    "{controller}/{action}/{id}"// URL with parameters
                    new {controller = "Home", action = "Index", id = UrlParameter.Optional} // Parameter defaults
                );


However, this will not always meet your needs.  In such case, you can create custom routes.  For instance, let's say it is a requirement that the "HR (Human Resource)"  department of your company should have their own unique URL in a pattern like this: "Hr/PersonalProfile/Display/1234".  Custom route can be utilized to make this work:

            routes.MapRoute
                (
                    "Hr"// The name must be unique in a route table
                    "Hr/PersonalProfile/{action}/{id}"// URL with parameters
                    new {controller = "PersonalProfile", action = "Display", id = UrlParameter.Optional} // Parameter defaults                );

Now you can display a personal profile using this URL: http://{yourdomian}/Hr/PersonalProfile/Display/1234

One very important thing to note is that MVC tries to find matching route in the order of the routes registration.

In our example, the custom route "Hr" must be registered before the default route is.  Otherwise, when the site is accessed with the URL "http://{yourdomian}/Hr/PersonalProfile/Display/1234", it matches the default route and it will try to look for a controller named "Hr" which doesn't exist.  This, of course, results in an error as below:

Server Error in '/' Application.

The resource cannot be found.

Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly.

Requested URL: /Hr/PersonalProfile/Display

Phil Haack created a very useful tool for debugging MVC routing: route debugger and you can get it through NuGet package management tool.  Just type in the following command in Package Manager Console:
PM> install-package routedebugger

If you're not familiar with NuGet, read about it here.  And download it from here.



Tuesday, August 11, 2009

using statement causes undesired result in WCF client.

I have a WCF service client which is a WinForms desktop application.  I have a method that is responsible for uploading certain information by consuming the WCF service.  I was initializing the proxy as follows:

using ( proxy = new WCFServiceClient. WCFServiceClient() ) {
proxy = new WCFServiceClient. WCFServiceClient() ;
proxy.UploadInfo();
}

It was working just fine.  Then I had to make some changes (added a new method to the business logic layer called by the service) on the server side, it compiled without any error and passed the unit test.  So I published it to my test site and ran a unit test against the test site.  To my surprise, I started getting the following error message: 
The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.

After bit of searching, I found this article.

According to this artical, one "should not use the C# "using" statement to automatically clean up resources when using a typed client".  The reason being, "The C# "using" statement results in a call to Dispose(). This is the same as Close(), which may throw exceptions when a network error occurs. Because the call to Dispose() happens implicitly at the closing brace of the "using" block, this source of exceptions is likely to go unnoticed both by people writing the code and reading the code. This represents a potential source of application errors."  That was exactly what was going on with my code.  The "using" statement was masking the actual error that was occurring on the server.  After removing the "using" statement and running the test again, I got the actual error which was the service couldn't find the new method that I had just added.  It turned out that the publishing tool didn't update the business logic DLLs.  The problem went away after forcing a replacement of the BLL DLLs.



Tuesday, August 4, 2009

Display Grid Page info ("Page # of Total Page Count")

The GridView control has the options to enable paging.  You can also specify different paging modes (NextPreviousFirstLast, Numeric, etc.) but it does not provide a way to display page info in the format of "Page 1 of 10" when you're in the mode of NextPriviousFirstLast mode.  So I decided to add my own.  Below the GridView control, I added a label control as follows:



I don't like to hard code strings into code if I can avoid it for internationlization reasons and for ease of editing at one place.  So I put all my messages in a resource file.   To display "Page # of #", I create a string resource named "PageNumberOfTotal" and its content is "Page {0} of {1}".  Then I handle the DataBound event of the GridView control as follows:

        protected void gdRecords_DataBound(object sender, EventArgs e)
        {
//If there are records to display, then display the message
            if (gdRecords.Rows.Count > 0)
            {
                lblNumberOfRecords.Visible = true;
                lblNumberOfRecords.Text = string.Format(
                   MessageResource.Properties.Resources.PageNumberOfTotal,
                    gdRecords.PageIndex + 1,
                    gdRecords.PageCount);
            } //If there isn't any records to display, the hide the label control
            else lblNumberOfRecords.Visible = false;
        }

Thursday, July 23, 2009

Populating controls in FormView Insert or Empty empty template with default values

FormView doesn't make it easy for a developer when he wants to populate the controls in a empty or insert template with default values.  After doing some search, I found out one way to accomplish this is to override ItemCreated event as follows:

        protected void fvMine_ItemCreated(object sender, EventArgs e)
        {
//if the current mode in insert mode
              if (fvMine.CurrentMode == FormViewMode.Insert)
              {
//get a reference to the control
                            txt = (TextBox) fvMine.Row.FindControl("txtCity");
                            if (txt != null)
                            {
// populate it with a default value
                                txt.Text = "New York";
                            }

Wednesday, April 15, 2009

Move selection to the next item in ListBox when the record is deleted in a FormView

In my previous post, I showed the method to highlight a newly inserted record from the FormView in the ListBox. Conversly, when a record is deleted from the FormView, I'd like to move to the next item in the ListBox if there is one. If the deleted item is last item, then move to the previous one.

Below is the definition of the ListBox:
<asp:ListBox ID="listBoxEmployees" runat="server"
AutoPostBack="true"
DataSourceID="odsListBoxEmployees"
DataTextField="EmployeeName"
DataValueField="EmployeeID"
onselectedindexchanged="listBoxEmployees_SelectedIndexChanged"
ondatabound="listBoxEmployees_DataBound">
</asp:ListBox>

Below is the definition of the FormView:
<asp:FormView
ID="fvEmployee"
runat="server"
DataKeyNames="EmployeeID"
DataSourceID="odsEmployee"
oniteminserted="fvEmployee_ItemInserted"
>

Below is the definition of the Object Data Source:

<asp:ObjectDataSource
ID="odsEmployee"
runat="server"
TypeName="Employees"
SelectMethod="SelectOne"
InsertMethod = "Insert"
UpdateMethod = "Update"
DeleteMethod = "Delete"
ConflictDetection="OverwriteChanges"
oninserted="odsEmployee_Inserted"
ondeleting="odsEmployee_Deleting"
>
<SelectParameters>
<asp:ControlParameter Name="EmployeeID" Type="Int32" Direction="Input" ControlID="listBoxEmployees" PropertyName="SelectedValue" />
</SelectParameters>
<InsertParameters>
<asp:Parameter Name="EmployeeName" Size="80" Direction = "Input" Type="String" />
</InsertParameters>
<UpdateParameters>
<asp:Parameter Name="EmployeeID" Type="Int32" Direction="Input" />
<asp:Parameter Name="EmployeeName" Size="80" Direction = "Input" Type="String" />
</UpdateParameters>
</asp:ObjectDataSource>

Handle Deleted event of the ODS so before the record is deleted in the FormView, we'll store the next item in the ListBox in view state as follows:

protected void odsEmployee_Deleting(object sender, ObjectDataSourceMethodEventArgs e)
{
//if there are more one items in the list
if (listBoxEmployees.Items.Count > 1)
//if the record to be deleted is not the last one in the list
if (listBoxEmployees.SelectedIndex < listBoxEmployees.Items.Count-1)
{
//store the next item's value
ViewState["EmployeeID"] = listBoxEmployees.Items[++listBoxEmployees.SelectedIndex].Value;
}
else
//if it is the last one, then store the previous item's value
ViewState["EmployeeID"] = listBoxEmployees.Items[--listBoxEmployees.SelectedIndex].Value;
}

The code above is self explanatory.

Next handle the DataBound event of the ListBox control as follows:

protected void listBoxEmployees_DataBound(object sender, EventArgs e)
{
if (listBoxEmployees.Items.Count > 0)
if (ViewState["EmployeeID"] != null)
{
listBoxEmployees.SelectedValue = ViewState["EmployeeID"].ToString();
}
else listBoxEmployees.SelectedIndex = 0;
ViewState.Remove("EmployeeID");
}

This will set the SelectedValue of the ListBox to the value in the view state. After we used the value in the view state, we remove it.

Highlight ObjectDataSource bound ListBox after ObjectDataSource bound FormView inserted a brand new record

I have a ListBox (I'll call it listBoxEmployees) that is bound to an ObjectDataSource (I'll call odsListBoxEmployees).

<asp:ListBox ID="listBoxEmployees" runat="server"
AutoPostBack="true"
DataSourceID="odsListBoxEmployees"
DataTextField="EmployeeName"
DataValueField="EmployeeID"
onselectedindexchanged="listBoxEmployees_SelectedIndexChanged"
ondatabound="listBoxEmployees_DataBound">
</asp:ListBox>

It displays Employee Name as Text and stores EmployeeID as Value in the list.

Then I have a FormView which is bound to another ObjectDataSource (I'll call it odsEmployee) which retrieves an individual record when an item is selected in the ListBox control. Below is the FormView definition:
<asp:FormView
ID="fvEmployee"
runat="server"
DataKeyNames="EmployeeID"
DataSourceID="odsEmployee"
>

Below is the ODS definition:
<asp:ObjectDataSource
ID="odsEmployee"
runat="server"
TypeName="Employees"
SelectMethod="SelectOne"
InsertMethod = "Insert"
UpdateMethod = "Update"
DeleteMethod = "Delete"
ConflictDetection="OverwriteChanges"
oninserted="odsEmployee_Inserted"
ondeleting="odsEmployee_Deleting"
>
<SelectParameters>
<asp:ControlParameter Name="EmployeeID" Type="Int32" Direction="Input" ControlID="listBoxEmployees" PropertyName="SelectedValue" />
</SelectParameters>
<InsertParameters>
<asp:Parameter Name="EmployeeName" Size="80" Direction = "Input" Type="String" />
</InsertParameters>
<UpdateParameters>
<asp:Parameter Name="EmployeeID" Type="Int32" Direction="Input" />
<asp:Parameter Name="EmployeeName" Size="80" Direction = "Input" Type="String" />
</UpdateParameters>
</asp:ObjectDataSource>

What I want to do after inserting a record from the FormView is to add the newly inserted record in the ListBox control and highlight it by making it the selected item. Below is how to achieve this:

Handle the Inserted event of odsForm as follows:

protected void odsForm_Inserted(object sender, ObjectDataSourceStatusEventArgs e)
{
ViewState["EmployeeID"] = e.ReturnValue;
}

This will store the employee id of the new inserted record in the view state.

And then handle the DataBound event of the ListBox as follows:

protected void listBoxEmployees_DataBound(object sender, EventArgs e)
{
if (listBoxEmployees.Items.Count > 0)
if (ViewState["EmployeeID"] != null)
{
listBoxEmployees.SelectedValue = ViewState["EmployeeID"].ToString();
}
else listBoxEmployees.SelectedIndex = 0;
ViewState.Remove("EmployeeID");
}

This will set the SelectedValue of the ListBox to the value in the view state. After we used the value in the view state, we remove it.

It works great.

The difference between Eval and Bind data binding functions in ASP.NET

When binding in ASP.NET within FormView, GridView or DetailsView, one could use data-binding expressions with this tag <%# %>. There are two functions, which are Eval and Bind, used frequently. For instance, suppose you a data source has the field named "ProductName", you could bind it as follows:

<%# Eval('ProductName')%> OR <%# Bind('ProductName')%>

So what is the difference between the two functions?
The difference is, according to MSDN, the Eval function is used to define one-way (read-only) binding. The Bind function is used for two-way (updatable) binding.

About Cullen

My photo
Christian, Father, Software Developer/Architect who enjoys technology and using it to make people's lives easier!

Followers