Wednesday, March 26, 2014

Zooming Visual Studio 2012 Code Editor (Repost)

Just received a newsletter from dotnet videos regarding zooming in/out the code editor. In that email, there were three ways. However, there are several options to do it as presented below:
1). Using the zoom drop down control below the code editor.
2). Using Keyboard combinations:
Zoom OUT = Ctrl + Shift + Comma, Zoom IN = Ctrl + Shift + Period
3). Type a zoom level directly in the the zoom control in the bottom left corner of the editor
4). Select a common zoom level from the dropdown list in the zoom control
5). Hold Ctrl key and scroll the mouse wheel (up/down).
References:
Visual Studio 2012 Zoom In or Zoom Out
Visual Studio 2010 Zoom In or Zoom Out
Cheers!

Thursday, March 20, 2014

ASP.NET MVC 4 Built-in Form Based Authentication

Given that I have some background knowledge of ASP.NET Web Forms Authentication, I decided to try experimenting on MVC 4 authentication/authorization framework. Most of the articles in the internet regarding forms authentication in ASP.NET MVC are custom based approach and less on the built-in technology which is WebData.WebSecurity usage. Not until I found these articles:
a. Forms Authentication Customized
b. Introduction to forms based authentication in MVC 4
c. Authenticating Users In Asp.net MVC 4
So, to cut the story short, I made an application which utilized the built-in WebMatrix authentication in MVC 4. The first thing to do, is to familiarize those articles to get a good grasp on the topic. The setup of my application are as follows:
1. Web.config
     1.1 Added authentication and custom errors
  <authentication mode="Forms">  
    <forms loginUrl="~/Account/Login" timeout="2880"/>    
   </authentication>  
   <authorization>  
     <allow users="*"/>     
   </authorization>  
   <customErrors mode="On" defaultRedirect="~/Error/Error">  
    <error statusCode="404" redirect="~/Errors/Http404" />  
   </customErrors>  
     1.2 Replaced the connection string to point it with an existing database. In my case it's northwind database.
  <add name="DefaultConnection" connectionString="Data Source=testServer;Initial Catalog=NORTHWIND;User ID=sa;Password=testsql2012;" providerName="System.Data.SqlClient" />  
Here's a sample image that Northwind has added the built in authentication/authorization tables.
2. In the built-in account controller Register() action, I added a code to map a default role which is a "Customer" to a new user. The other role is "Administrator" which will be set explicity through the database or admin page.
Code:
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                try
                {                    
                    WebSecurity.CreateUserAndAccount(model.UserName, model.Password);     
                    //assign default role to new user.     
                    Roles.AddUserToRole(model.UserName, "Customer");                   
                    WebSecurity.Login(model.UserName, model.Password);
                    return RedirectToAction("Index", "Customer");
                }
                catch (MembershipCreateUserException e)
                {
                    ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

3. I added an Errors Controller(ErrorsController.cs) with the following methods that handles 404 and unauthorized exceptions.
Code:
protected override void HandleUnknownAction(string actionName)
        {
            if (this.GetType() != typeof(ErrorsController))
            {
                var errorRoute = new System.Web.RoutingRouteData(); //ako gi change added assembly
                errorRoute.Values.Add("controller", "Errors");
                errorRoute.Values.Add("action", "Http404");
                errorRoute.Values.Add("url", HttpContext.Request.Url.OriginalString);
                View("Http404").ExecuteResult(this.ControllerContext);
            }
        }

        public ActionResult Http404()
        {
            return View();
        }

        public ActionResult Error()
        {
            return View();
        }

        public ActionResult InvalidUser()
        {
            return PartialView("_InvalidUser");
        }

        public ActionResult UnAuthorizedUser()
        {
            return PartialView("_UNAuthorizedUser");
        }

4. I added the class AuthorizeUsersAttribute in my Models folder and decorated my controller actions in CustomerController.cs with attribute as presented in this post: Redirect Unauthorized Access to Custom View in MVC 4
Code:
 [AuthorizeUsers(Roles = "Administrator", NotifyUrl = "/Errors/UnAuthorizedUser")]
        [HttpPost]
        public ActionResult Create(Customer customer)
        {
            if (ModelState.IsValid)
            {
                db.Customers.Add(customer);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(customer);
        }

5. I added partial view in shared folder for notifying unauthorized users.
_UNAuthorizedUser.cshtml
6. Add this in global.asax or RouteConfig.cs RegisterRoutes() method
Code:
WebMatrix.WebData.WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);

7. I didn't revise anything in AccountModels.cs
8. In my sample project, the administrator role can create, edit, delete and view customer information. The customer role is limited to viewing only. Here are some sample images:
     8.1 The default page automatically redirects to the login page for authorization and authentication.      8.2 The main view for users with admin or customer role.

     8.3 Page restriction on a view accessed by a customer user.

     8.4 Edit Page authorized to admin users.

:)

Wednesday, March 19, 2014

Redirect unauthorized access to a custom view instead of redirecting to a login view in ASP.NET MVC 4

One might encounter when implementing the forms authentication framework(WebMatrix)is that when a user access a specific url/controller and he/she is unauthorized, the application always redirect's to the default log-in view. In order to solve this minor issue, one solution is to develop a custom class that inherit's the AuthorizeAttribute class and override the HandleUnauthorizedRequest method as shown below:
Code:
public class AuthorizeUsersAttribute : AuthorizeAttribute
    {
        private string redirectUrl = "";
        
        public string NotifyUrl
        {
            get { return redirectUrl; }
            set { redirectUrl = value; }
        }

        public AuthorizeUsersAttribute()
            : base()
        {
        }

        public AuthorizeUsersAttribute(string redirectUrl)
            : base()
        {
            this.redirectUrl = redirectUrl;
        }

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAuthenticated)
            {
                string authUrl = this.redirectUrl; //passed from attribute NotifyUrl Property

                //if null, get it from config
                if (String.IsNullOrEmpty(authUrl))
                    authUrl = System.Web.Configuration.WebConfigurationManager.AppSettings["RolesAuthRedirectUrl"];

                if (!String.IsNullOrEmpty(authUrl))
                    filterContext.HttpContext.Response.Redirect(authUrl);
            }

            //else do normal process
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
Sample usage on a controller:
Code:
[AuthorizeUsers(Roles = "Administrator", NotifyUrl = "/Errors/UnAuthorizedUser")]
public ActionResult Delete(string id = null)
{
    Customer customer = db.Customers.Find(id);
    if (customer == null)
    {
        return RedirectToAction("Errors", "Http404");      
    }
    return View(customer);
}

Based from the code above, only administrator's can access the page. Once an unauthorized activity happens, it will redirect to an UnAuthorizedUser action from Errors controller. The action might as well render a partial view or customized code.

Cheers!

Tuesday, March 18, 2014

You must call the "WebSecurity.InitializeDatabaseConnection" method before you call any other method of the "WebSecurity" class

In the Account Controller Register action (public ActionResult Register(RegisterModel model)) I have a code below that by default assign a Customer Role to a new user during registration. In my database, the defined roles are "Administrator" and "Customer". However, the code below generates exception as stated on the title post.
Code:
SimpleRoleProvider role = new SimpleRoleProvider();
role.AddUsersToRoles(new string[] { model.UserName }, new string[] { "Customer" });
The solution would be to use the Role class defined in System.Web.Security namespace instead of SimpleRoleProvider:
Code:
Roles.AddUserToRole(model.UserName, "Customer");

Reference: Perils of MVC 4 AccountController
Cheers! :)

Saturday, March 15, 2014

Render ASP.NET MVC 4 Partial View based from Html.DropdownList() selected value using jQuery

In my previous post on loading items to Select control, I decided to create a more advanced example by rendering an asp.net mvc partial view using jquery based on drop down selection. The mvc application will simply load all orders irregardless of the status made by a particular customer selected from the dropdown list. The application also calculates the total orders made by the customer using jquery numberformatter framework.
Partial View:
 @model IList<ShowWebGridUsingJQuery.Models.SalesOrderHeader>  
 @{  
   Layout = Request.IsAjaxRequest() ? null : "~/Views/Shared/_Layout.cshtml";  
 }  
 @{  
   var orderTotal = Model.Sum(o => (float)o.TotalDue);  
   WebGrid grid = new WebGrid(Model);  
 }  
 <script type="text/javascript">  
   $(document).ready(function () {  
     var total = 0;  
     $('#divGrid .totalDue').each(function () {  
       total = total + parseFloat($(this)[0].innerHTML.toLocaleString().replace(",", ""));  
     });  
     $('table').append('<tfoot><tr><td colspan="7" style="text-align:right;"><b>Total</b></td><td style="text-align:center;"><b>' + NumberFormatter(total) + '</b></td></tr></tfoot>');  
   });  
   //using jquery plugin  
   function NumberFormatter(amount) {  
     var n = $.formatNumber(amount, { format: "#,###.00", locale: "us" });  
     return n;  
   }  
 </script>  
 <div id="divGrid">  
   @grid.GetHtml(  
     tableStyle: "webgrid", headerStyle: "webgrid-header", footerStyle: "webgrid-footer", alternatingRowStyle: "webgrid-alternating-row",  
     selectedRowStyle: "webgrid-selected-row", rowStyle: "webgrid-row-style",  
     columns:grid.Columns(  
       grid.Column("SalesOrderNumber", "Order ID"),  
       grid.Column("AccountNumber", "Account Number"),  
       grid.Column("OrderDate", "Order Date", format: (item) => string.Format("{0:yyyy-MM-dd}", item.OrderDate)),  
       grid.Column("CreditCardID","Credit Card ID"),  
       grid.Column("SubTotal","Sub Total", format: (item) => string.Format("{0:0,0.00}", item.SubTotal)),   
       grid.Column("TaxAmt","Tax Amount",format: (item) => string.Format("{0:0,0.00}", item.TaxAmt)),  
       grid.Column("Freight","Freight",format: (item) => string.Format("{0:0,0.00}", item.Freight)),  
       grid.Column("TotalDue","Total Due",format: (item) => string.Format("{0:0,0.00}", item.TotalDue), style: "totalDue"))  
      )  
 </div>  
Index View:
 <script type="text/javascript">  
   $(document).ready(function () {  
     $('#dvSalesOrdersLoader').hide();  
     $("#Customer").change(function () {  
       if ($("#Customer").val() != "Select") {  
         //show div with loading image (processing request)  
         $('#dvSalesOrdersLoader').show();  
         //working ajax  
         $.ajax({  
           url: '/Home/StateProvinces',  
           type: 'POST',  
           data: "CustomerID=" + $("#Customer").val(),            
           dataType: 'html'  
         })  
           .success(function (result) {  
             $('#dvSalesOrders').html("");  
             $('#dvSalesOrdersLoader').hide();  
             $('#dvSalesOrders').show();  
             $('#dvSalesOrders').html(result);  
           })  
           .error(function(xhr, status) {  
             alert(status);  
           });  
       }  
       else {  
         $('#dvSalesOrdersLoader').show();  
       }  
     });  
   });  
 </script>  
 @*@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "countryRegionsForm" }))*@  
 @using (Html.BeginForm())  
  {  
   @Html.AntiForgeryToken()  
   <h4>Select Customer Name:</h4>  
   <hr />  
    @Html.ValidationSummary()  
   <div>  
     @Html.Label("Select CustomerInfo:")  
     <div>  
       @Html.DropDownList("Customer", ViewData["CustomerInfo"] as SelectList)  
     </div>  
   </div><br />  
    <div>  
     @Html.Label("Order List")  
       <div id="dvSalesOrdersLoader" style="width: 100%; height: 130px">  
         <table style="width: 100%; height: 100%">  
           <tr>  
             <td>  
               <img src="~/Images/loader.gif" style="margin-top: 55px; margin-left: 200px" alt="not showing"/>  
             </td>  
           </tr>  
         </table>   
       </div>  
       <div id="dvSalesOrders" style="width: 100%; height: 100%; overflow:hidden; display:none">  
       </div>  
   </div>  
  }  
Controller:
Code:
private CustomerWithOrders context = new CustomerWithOrders();

        public ActionResult Index()
        {
            SelectList customers;

            // Join on the ID properties.
            var query = (from c in context.Customers
                        join p in context.People on c.CustomerID equals p.BusinessEntityID
                        select new 
                        { 
                            FullName =  p.FirstName + " " + (p.MiddleName != null ? p.MiddleName : "") + " " + p.LastName,
                            ID = c.CustomerID
                        }).ToList().OrderBy(t=>t.FullName);

            customers = new SelectList(query.ToList(), "ID", "FullName");
            ViewData["CustomerInfo"] = customers;

            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult StateProvinces(string CustomerID)
        {
            int temp = Convert.ToInt32(CustomerID);
            List<SalesOrderHeader> orderDetails = new List<SalesOrderHeader>();

            (from sales in context.Sales_Order_Header
             where sales.CustomerID == temp   
             select sales).ToList().ForEach(item =>
                     {
                         orderDetails.Add(item);
                     });
                        
            return View("~/Views/Shared/_SalesOrders.cshtml", orderDetails);
        }
Customer with sales orders:

Customer without sales orders:
Cheers!

Friday, March 14, 2014

Populate Select/ListBox items from Html.DropdownList() selected value using jQuery in ASP.NET MVC 4

After familiarizing some basic concepts on ASP.NET MVC 4, I decided to create a simple application which populates a listbox control from a DropDownList helper selected value using jQuery. This simple application included the Entity Framework which targets the AdventureWorks DB.
Here's the Model Class:
Code:
  public class CountryRegionsContext : Models.AdventureWorks2008Entities
    {
        public DbSet<CountryRegion> Country_Regions { get; set; }
        public DbSet<StateProvince> State_Province { get; set; }
    }
Here's the View page:
 @{  
   ViewBag.Title = "Index";  
   Layout = "~/Views/Shared/_Layout.cshtml";  
 }  
 <h2>Adventure Works Country and State Province Information</h2>  
 <script>  
   $(document).ready(function () {  
     $("#State").prop("disabled", true);  
     $("#Country").change(function () {  
       if ($("#Country").val() != "Select") {  
         var CountryProvinces = {};  
         CountryProvinces.url = "/CountryRegions/StateProvinces";  
         CountryProvinces.type = "POST";  
         CountryProvinces.data = JSON.stringify({ Country: $("#Country").val() });  
         CountryProvinces.datatype = "json";  
         CountryProvinces.contentType = "application/json";  
         CountryProvinces.success = function (StateProvinceList) {  
           $("#State").empty();  
           if (StateProvinceList != undefined) {  
             if (StateProvinceList.length > 0) {  
               for (var i = 0; i < StateProvinceList.length; i++) {  
                 $("#State").append("<option>" + StateProvinceList[i] + "</option>");  
               }  
               $("#State").prop("disabled", false);  
             }  
             else  
               alert("No State or Region for that Country!");  
           }  
           else {  
             alert("No State or Region for that Country!");  
           }  
         };  
         CountryProvinces.error = function ()  
         {  
           alert("Error in Retrieving State Province Information!");  
         };  
         $.ajax(CountryProvinces);  
       }  
       else {  
         $("#State").empty();  
         $("#State").prop("disabled", true);  
       }  
     });  
   });  
 </script>  
 @using (Html.BeginForm("Index", "CountryRegions",   
   FormMethod.Post,  
   new { id = "countryRegionsForm" }))  
 {  
   @Html.AntiForgeryToken()  
   <h4>Select Country & States</h4>  
   <hr />  
    @Html.ValidationSummary()  
   <div>  
     @Html.Label("Select Country:")  
     <div>  
       @Html.DropDownList("Country", ViewData["CountryInfo"] as SelectList)  
     </div>  
   </div><br />  
   <div>  
     @Html.Label("State Province")  
     <div>  
        <select id="State" name="lstStates" size="15" style="width:300px;"></select>  
     </div>  
   </div>  
 }  
Here's the controller class:
Code:
public class CountryRegionsController : Controller
    {
        private CountryRegionsContext context = new CountryRegionsContext();
        private List<CountryRegion> CountryNameList = new List<CountryRegion>();
        private List<string> StateProvinceList = new List<string>();

        // GET: /CountryRegions/
        public ActionResult Index()
        {            
            SelectList countries;
            if (context.Country_Regions.ToList().Count > 0)
            {
                CountryNameList.AddRange(context.Country_Regions.ToList().OrderBy(t => t.Name));
                countries = new SelectList(CountryNameList, "CountryRegionCode", "Name");
                ViewData["CountryInfo"] = countries;
            }
            
            return View();
        }

        public JsonResult StateProvinces(string Country)
        {
            (from province in context.State_Province
            where province.CountryRegionCode == Country
            select new
            {
                name = province.Name
            }).ToList().ForEach(data => 
                {
                    StateProvinceList.Add(data.name);
                }); 
                      
            return Json(StateProvinceList);
        }
}
Sample output page without record:
Sample output page with record:

Wednesday, March 12, 2014

Add placeholder (watermark) to Html.TextBoxFor() helper in ASP.NET MVC 4

After working with simple form html elements, I decided to give it a try applying the placeholder jquery framework to ASP.NET MVC4 application. The steps are similar in this post: Placeholder attribute in HTML5 form Elements except that the target controls are HTML Helpers.

Basically, TextBoxFor() helper when rendered to the browser is an input text element. So, let's give it a spin. On your _Layout.cshtml, reference the jquery and placeholder scripts.
 <script type="text/javascript" src="~/Scripts/jquery-1.7.1.min.js"></script>  
 <script type="text/javascript" src="~/Scripts/placeholders.jquery.min.js"></script>  
and in your MVC Form, apply it to TextBoxFor() as shown below:
 @model TextBoxFor.Models.Movie  
 @{  
   ViewBag.Title = "CreateMovie";  
 }  
 <h2>Create</h2>  
 @using (Html.BeginForm()) {  
   @Html.ValidationSummary(true)  
   <fieldset>  
     <legend>Movie</legend>  
     <div class="editor-label">  
       @Html.LabelFor(model => model.Title)  
     </div>  
     <div class="editor-field">  
       @Html.EditorFor(model => model.Title)  
       @Html.ValidationMessageFor(model => model.Title)  
     </div>  
     <div class="editor-label">  
       @Html.LabelFor(model => model.Price)  
     </div>  
     <div class="editor-field">  
       @Html.EditorFor(model => model.Price)  
       @Html.ValidationMessageFor(model => model.Price)  
     </div>  
     <div class="editor-label">  
       @Html.LabelFor(model => model.ReleaseDate)  
     </div>  
     <div class="editor-field">  
       @Html.TextBoxFor(m => m.ReleaseDate, "{0:yyyy-MM-dd}",  
           new { placeholder = "yyyy-MM-dd" })  
       @Html.ValidationMessageFor(model => model.ReleaseDate)  
     </div>  
     <div class="editor-label">  
       @Html.LabelFor(model => model.Genre)  
     </div>  
     <div class="editor-field">  
       @Html.EditorFor(model => model.Genre)  
       @Html.ValidationMessageFor(model => model.Genre)  
     </div>  
     <div class="editor-label">  
       @Html.LabelFor(model => model.Rating)  
     </div>  
     <div class="editor-field">  
       @Html.EditorFor(model => model.Rating)  
       @Html.ValidationMessageFor(model => model.Rating)  
     </div>  
     <p>  
       <input type="submit" value="Create" />  
     </p>  
   </fieldset>  
 }  
 <div>  
   @Html.ActionLink("Back to List", "Index")  
 </div>  
 @section Scripts {  
   @Scripts.Render("~/bundles/jqueryval")  
 }  
Sample Output:
:)

Change default start page of ASP.NET MVC 4 application

Familiarizing myself with ASP.NET MVC 4 made me think, how can I change the default start page of using global.asax? The globax.asax only has declarations that calls methods and lacking the methods as seen in MVC 2-3 versions. Luckily, the structure of the project has been changed since the Routes have been transfered to App_Start folder. Below is the sample code to change the default start page using the the class RouteConfig.
Code:
public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    //routes.MapRoute(
    //    name: "Default",
    //    url: "{controller}/{action}/{id}",
    //    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    //);

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
                defaults: new { controller = "Movies", action = "Index", id = UrlParameter.Optional }
            );
        }
Reference: App_start and global.asax in ASP.NET MVC 4

Tuesday, March 11, 2014

Placeholder attribute in HTML5 not showing on IE 9 and below (Watermark feature)

Given this html markup for input text element for accepting email value:
 <input type="email" name="inEmail" id="inEmail" required="required" placeholder="yourname@domain.com" />  
The place holder shows correctly on firefox and google chrome but not on IE 9. After searching the internet, I found placeholder framework that will fix place holders in IE 9 and below.
The steps are as follows:
1. Download the placeholder script here: Placeholder js
2. Add reference to jquery and placeholder on your html file.
 <script src="../Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>  
 <script src="placeholders.jquery.min.js" type="text/javascript"></script>  
IE demo:
That's it... :)

Friday, March 7, 2014

The type specified in the TypeName property of ObjectDataSource 'ObjectDataSource1' could not be found (ASP.NET Webservice)

As I was updating one of my ASP.NET application to 4.5, running the app generates an error as stated above. I remembered that the Object Datasource control was dependent on a webservice. So, after reviewing the new configuration of the webservice, the port, url and namespace have changed. So, here are the steps to make my app work again.
Steps:
 1. Update the web service .discomap file through Add Service Reference and then choosing advanced to target it as .NET 2.0 platorm. Though Service Reference should be recommended or WCF service.  
 2. Change Web.Config setting of the web service including it's IP and Port. Example:<br>  
   <add key="localhost.ECommerceService" value="http://192.168.2.1:1448/WebDeployServer/QuotesPaymentService.asmx"/><br>  
   to<br><add key="localhost.ECommerceService" value="http://192.168.2.1:14070/WebDeployServer/QuotesPaymentService.asmx"/>  
 3. Configure again the object Datasource to update it's TypeName value.<br>  
   Example of an updated TypeName:   
      TypeName="localhost.QuotesPaymentService".  
Cheers!

Monday, March 3, 2014

Prevent saving changes that require the table re-creation (SQL Server Error in Updating Primary Key Is Identity)

Good Day!

I forgot to set the identity of the primary key of field Id in table Products. After inserting records through insert statements, an error occurs since the column Id does not allow null values. So, I tried changing the Is Identity to true but unluckily I'm stuck with the an error "Prevent saving changes that require the table re-creation". Additional details are as follows: ID field has a constraint called PK_Products. So, after googling a while I came up with series of steps.

Note: You have to close the design view of the table in the Management Studio to perform the steps below.
 -- 1  
 ALTER TABLE Products DROP CONSTRAINT PK_Products  
 GO  
 -- 2  
 Alter Table Products Drop Column Id  
 Go   
 -- 3  
 Alter Table Products Add Id_new Int Identity(1,1)  
 Go   
 -- 4  
 Exec sp_rename 'Products.Id_new', 'Id','Column'  
 Go  
 -- 5  
 ALTER TABLE Products Add CONSTRAINT PK_Products Primary Key (ID)  
 GO  
Where: Products is the table name and Id as the primary key field. Additional information and explanations are found in the links provided below:

References:
a. Alter Constraint
b. How to alter column to identity(1,1)
Cheers!

Sunday, March 2, 2014

Custom Richtextbox control with Watermark Support in VB.NET

Here's the VB.NET Version of this Custom Control from this post: Custom Richtextbox control with Watermark Support in C#
Option Strict On
Option Infer On
 
Imports System.Drawing
Imports System.ComponentModel
 
''' <summary>
''' Set Watermark in RichTextbox.
''' </summary>
Public Class WatermarkRichTextbox
    Inherits Windows.Forms.RichTextBox
    Private m_watermark As String
    Private m_watermarkColor As Color
    Private m_foreColor As Color
    Private empty As Boolean
 
    <Browsable(True)> _
    Public Property WatermarkColor() As Color
        Get
            Return m_watermarkColor
        End Get
        Set(value As Color)
            m_watermarkColor = value
            If empty Then
                MyBase.ForeColor = m_watermarkColor
            End If
        End Set
    End Property
 
    <Browsable(True)> _
    Public Property Watermark() As String
        Get
            Return m_watermark
        End Get
        Set(value As String)
            m_watermark = value
            If empty Then
                MyBase.Text = m_watermark
                MyBase.ForeColor = m_watermarkColor
            End If
        End Set
    End Property
 
    Public Sub New()
        empty = True
        m_foreColor = ForeColor
    End Sub
 
    <Browsable(True)> _
    Public Shadows Property ForeColor() As Color
        Get
            Return m_foreColor
        End Get
 
        Set(value As Color)
            m_foreColor = value
            If Not empty Then
                MyBase.ForeColor = value
            End If
        End Set
    End Property
 
    Public Overrides Property Text() As String
        Get
            If empty Then
                Return ""
            End If
            Return MyBase.Text
        End Get
        Set(value As String)
            If value = "" Then
                empty = True
                MyBase.ForeColor = m_watermarkColor
                MyBase.Text = m_watermark
            Else
                MyBase.Text = value
            End If
        End Set
    End Property
 
    Protected Overrides Sub OnGotFocus(e As EventArgs)
        If empty Then
            empty = False
            MyBase.ForeColor = m_foreColor
            MyBase.Text = ""
        End If
 
        MyBase.OnGotFocus(e)
    End Sub
 
    Protected Overrides Sub OnLostFocus(e As EventArgs)
        MyBase.OnLostFocus(e)
        If MyBase.Text = "" Then
            empty = True
            MyBase.ForeColor = m_watermarkColor
            MyBase.Text = m_watermark
        Else
            empty = False
        End If
    End Sub
End Class

Custom Richtextbox control with Watermark Support in C#

There was a solution in MSDN Forums on how to add watermark to a Textbox control. I tried replacing the base class if this will work on a RichTextbox control. After testing, the custom control works as expected.
Code:
/// <summary>
    /// Set Watermark in RichTextbox.
    /// </summary>
    public class WatermarkRichTextbox : RichTextBox
    {
        private string watermark;
        private Color watermarkColor;
        private Color foreColor;
        private bool empty;

        [Browsable (true)]
        public Color WatermarkColor 
        {
            get 
            { 
                return watermarkColor; 
            }
            set 
            {
                watermarkColor = value;
                if (empty) 
                {
                    base.ForeColor = watermarkColor;
                }
            }
        }

        [Browsable(true)]
        public string Watermark
        {
            get 
            { 
                return watermark; 
            }
            set 
            {
                watermark = value;
                if (empty) 
                {
                    base.Text = watermark;
                    base.ForeColor = watermarkColor;
                }
            }
        }

        public WatermarkRichTextbox()
        {
            empty = true;
            foreColor = ForeColor;
        }

        [Browsable(true)]
        public new Color ForeColor 
        {
            get 
            {
                return foreColor; 
            }
              
            set 
            {
                foreColor = value;
                if (! empty)
                    base.ForeColor = value;
            }
        }

        public override string Text 
        {
            get
            {
                if (empty)
                    return "";
                return base.Text;
            }
            set 
            {
                if (value == "") 
                {
                    empty = true;
                    base.ForeColor = watermarkColor;
                    base.Text = watermark;
                } 
                else 
                    base.Text = value;
            }
        }

        protected override void OnGotFocus (EventArgs e) 
        {
            if (empty) 
            {
                empty = false;
                base.ForeColor = foreColor;
                base.Text = "";
            }
            
            base.OnGotFocus (e);
        }

        protected override void OnLostFocus (EventArgs e) 
        {
            base.OnLostFocus (e);
            if (base.Text == "") 
            {
                empty = true;
                base.ForeColor = watermarkColor;
                base.Text = watermark;
            } 
            else
                empty = false;
        }
    }
Credits to the original author/programmer for submitting this kind of solution.

Saturday, March 1, 2014

Using PATINDEX() in SQL Server as an alternative to embedd Regular Expressions in SQL

This was based on a post from SQL Team on how to grab a 5 digit number from the string field which could utilize a regular expression like this: [0-9 ]{5}. The initial solution was given by a forum member named Kristen. It could extract the 5 digit mark on a string field as shown below:
 DECLARE     @strTest varchar(8000)  
 SELECT @strTest = '\\servername\foldername99999\filename.ext'  
 SELECT [Position]=PATINDEX('%[0-9][0-9][0-9][0-9][0-9]%', @strTest),  
      [Before]=SUBSTRING(@strTest, 1, PATINDEX('%[0-9][0-9][0-9][0-9][0-9]%', @strTest)-1),  
      [After]=SUBSTRING(@strTest, PATINDEX('%[0-9][0-9][0-9][0-9][0-9]%', @strTest), LEN(@strTest))  
What if the string field would contain two or more 5 digit information, how can you achieve that? The answer is to include while loop in TSQL and some additional string functions to achieve the desired output. Here's a sample stored procedure:
 USE TESTDB;  
 GO  
 CREATE PROCEDURE spGetFiveDigits  
      @strTest1 varchar(500),  
      @strPattern varchar(200)  
 AS  
 DECLARE @strSearchPos int  
 SELECT @strSearchPos = 1  
 WHILE PATINDEX(@strPattern, @strTest1) != 0  
 BEGIN  
  SELECT  
      [Position]=PATINDEX(@strPattern, @strTest1),  
      [Before]=SUBSTRING(@strTest1, 1, PATINDEX(@strPattern, @strTest1) - 1),  
      [After]=SUBSTRING(@strTest1, PATINDEX(@strPattern, @strTest1), LEN(@strTest1)),  
      [Five_Digits]=SUBSTRING(@strTest1, PATINDEX(@strPattern, @strTest1), 5),  
      [Variable_Tested] = @strTest1;  
           set @strSearchPos = PATINDEX(@strPattern, @strTest1)  
           set @strTest1 = SUBSTRING(@strTest1, PATINDEX(@strPattern, @strTest1) + 5, LEN(@strTest1))  
 END  
 GO  
Running the stored procedure with two 5 digit string data:
 EXEC spGetFiveDigits @strTest1 = N'12345\\servername\foldername\filename11111.ext',   
      @strPattern = N'%[0-9][0-9][0-9][0-9][0-9]%';  
Running the stored procedure with five 5 digit string data:
 EXEC spGetFiveDigits @strTest1 = N'\\s12345ervername88888\folde54326rname99999\filename11111.ext',   
      @strPattern = N'%[0-9][0-9][0-9][0-9][0-9]%';