Showing posts with label custom html helpers. Show all posts
Showing posts with label custom html helpers. Show all posts

Custom Validation Message Helper in asp.net mvc

Udemy
As i wrote earlier a post about Creating Custom Html Helpers in asp.net mvc which emphasized on how we can write custom html helper extensions in asp.net mvc according to the need, so that we can reuse them in the whole application, instead of writing plan html in View.

The example in that article was using ActionLink, today i am going to tell how we can implement custom Validation Message helper.I wanted to modify the validation message displaying in my application so that it displays * in front of required fields and the error message in tooltip of it like:





For that add a class in the project and add an extension method which will render our custom html that will be displayed for error message:

namespace CustomValidationMessageHelper.Helpers
{
    public static class Validator
    {
        public static MvcHtmlString MyValidationMessageFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
        {

            TagBuilder containerDivBuilder = new TagBuilder("div");
            containerDivBuilder.AddCssClass("tip_trigger");
            containerDivBuilder.InnerHtml = "*";


            TagBuilder midDivBuilder = new TagBuilder("div");
            midDivBuilder.AddCssClass("classic");
            midDivBuilder.AddCssClass("tip");
            midDivBuilder.InnerHtml = helper.ValidationMessageFor(expression).ToString();

            containerDivBuilder.InnerHtml += midDivBuilder.ToString(TagRenderMode.Normal);

            return MvcHtmlString.Create(containerDivBuilder.ToString(TagRenderMode.Normal));
        }
    }

}

and then define following css in a css file in my case it is site.css or you can add it in the view:

.validated {
    border-color: #DCE4EC !important;
}

textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"], .uneditable-input {
    padding: 3px 3px;
    border: 1px solid #DCE4EC;
}


        
.tip {
    background: none repeat scroll 0 0 #FFFFFF;
    border: 1px solid #808080;
    border-radius: 10px;
    box-shadow: 0 1px 10px rgba(32, 32, 32, 0.5);
    color: red;
    display: none;
    font-size: 12px;
    font-style: normal;
    margin-left: 10px;
    margin-top: -24px;
    padding: 4px;
    position: absolute;
    z-index: 999999;
}

.tip_trigger {
    width: 10px;
    float: right;
    color: red;
    margin-left: 3px;
}

Now we have to add client side code, which i have written in jquery in a js file or directly in view, in my case i have it in CustomValidation.js file:

$(document).ready(function () {
    //Tooltips
    var tip;
    $(".tip_trigger").hover(function () {
        console.log("hovered");
        tip = $(this).find('.tip');
        console.log($(this).find('.tip').find('span').html())
        if ($(this).find('.tip').find('span').html() != '') {
            $(this).find('.tip').show(); //Show tooltip
        }
    }, function () {
        $(this).find('.tip').hide(); //Hide tooltip 

    });

    ////Required fields
    $('input').each(function () {
        var req = $(this).attr('data-val-required');
        if (undefined != req) {
            $(this).css("border-color", "#DA9BA2")

        }
        if ($(this).val() != '') {

            $(this).addClass("validated");

        }

    });

    $('input').blur(function () {

        if ($(this).val() != '') {

            $(this).addClass("validated");
        }
        else {

            $(this).css("border-color", "#DA9BA2")
        }

    });


});


Now in the View add the reference to the related js and css files in the head section of View:

    <link href="@Url.Content("~/Content/site.css")" rel="stylesheet"/>
    <script src="@Url.Content("~/Scripts/jquery-1.9.1.js")"></script>
    <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/CustomValidation.js")" type="text/javascript"></script>


Now in your view add using statement of the namespace and now you can access the Helper method in the View:

@model CustomValidationMessageHelper.ViewModels.SignUpViewModel
@using CustomValidationMessageHelper.Helpers
@{
    Layout = null;
}


@Html.TextBoxFor(model => model.FirstName, new { @class = "form-control input-sm" })
@Html.MyValidationMessageFor(model => model.FirstName)

The sample project can be  downloaded from here



Image ActionLink Html Helper in asp.net mvc

Udemy
For creating a link in asp.net mvc we use Link Extension provided by  the mvc framework. For creating a simple anchor tag we use Html.ActionLink() helper which generates anchor tag for us.

For Example:

@Html.ActionLink("Link Display Text","Index","Home")

This will render following html:

<a href="/Home/Index">Link Display Text</a>

Now if we want to create a image link, we can use html to create image link this way:

<a href="/Home/Index">
<img src="/images/untitled.png">
</a>

This will work obviously,but what if we want to do it with Html Helper method as we do using Html.ActionLink, but we do not have any helper for image link provided by framework, so one can do it using html as i wrote above or will have to write custom html helper.

It's the beauty of asp.net mvc that we can extend exisiting helpers according to our needs and can also add new html helpers in case we need to used it at many places , in that case better approach is to create a helper extesnion and use it every where in the project.

Now for creating helper extension first of all we need to create a static class, as its the pre-requisite for creating extesnion methods that the method should be static, and it  should be inside a static class.

Here is the code for extension method for ImageActionLink helper extension:

namespace MyApplication.Helpers
{
  public static class CustomHtmlHelepers
  {
    public static IHtmlString ImageActionLink(this HtmlHelper htmlHelper, string linkText, string action, string controller, object routeValues, object htmlAttributes,string imageSrc)
    {
        var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
        var img = new TagBuilder("img");
        img.Attributes.Add("src", VirtualPathUtility.ToAbsolute(imageSrc));
        var anchor = new TagBuilder("a") { InnerHtml = img.ToString(TagRenderMode.SelfClosing) };
        anchor.Attributes["href"] = urlHelper.Action(action, controller, routeValues);
        anchor.MergeAttributes(new RouteValueDictionary(htmlAttributes));

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

    }
  }
}



The first parameter with this keyword is used in extension methods see this article on Extension Method for understanding what are extesnion methods.

and now we can call it from View for creating Image Link. But remember that we will have to include the namespace in the View in which we have create the class and extension method,but if you have create it in the same namespace, then it will be accessible without adding any using statement in View.

In my case i have seperated all Extension Methods in seperate namespace named Helpers so i will have to include it in View via using statement:

@using MyApplication.Helpers;

@Html.ImageActionLink("Link Display Text","Index","Home",null,null,"~/images/untitled.png")

It will render the same html which i wrote above which is :

<a href="/Home/Index">
<img src="/images/untitled.png">
</a>

I hope it makes you understand how you can write you own custom html helpers in asp.net mvc.




Creating Custom Html Helper Extensions in asp.net mvc

Udemy
Hi,

Today I will tell about how to write custom html helpers in asp.net mvc. I will show how to create custom html helper for ActionLink, normally we write Html.ActionLink(parameters) and it renders anchor tag in response as html on the page.

I had a requirement where I needed to check that if user is in specific role then link should render otherwise it will not render on page, so it is very akward to write if blocks in every view where I need to hide links on the basis of role so after researching a little, I came to know that we can write custom extensions according to the requirements.

So I wrote a custom helper that checked the role of the user and deciceds that it should render or not.

ActionLink method exisits inside LinkExtension class which is a static class, so we need to create a static class with name LinkExtensions:


public static class LinkExtensions
{
}

Now in it I will write one overload for my custom extension as I will utitlize that, we can create all overloads that are available for ActionLink same way we are creating this one but for this article I will just share one specific overload that I will be using:


namespace TestCustomHelper.Html
{

public static class LinkExtensions
{
public static MvcHtmlString ActionLinkAuthorized(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes, bool showActionLinkAsDisabled)
  {
     if (htmlHelper.ActionAuthorized(actionName, controllerName))
     {
       return htmlHelper.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes);
     }
     return MvcHtmlString.Empty;
}

}

Here is the ActionAuthorized method which also an Action Extension, it returns bool value by checking that user is authorized to call this action of controller or not and on the basis of value returned by this method it decides weather render the actionlink or not:


namespace HealthAccessPoint.Extensions
{
    public static class ActionExtensions
    {
        public static bool ActionAuthorized(this HtmlHelper htmlHelper, string actionName, string controllerName)
        {
            ControllerBase controllerBase = string.IsNullOrEmpty(controllerName) ? htmlHelper.ViewContext.Controller : htmlHelper.GetControllerByName(controllerName);
            ControllerContext controllerContext = new ControllerContext(htmlHelper.ViewContext.RequestContext, controllerBase);
            ControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor(controllerContext.Controller.GetType());
            ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);

            if (actionDescriptor == null)
                return false;

            FilterInfo filters = new FilterInfo(FilterProviders.Providers.GetFilters(controllerContext, actionDescriptor));

            if (!htmlHelper.CheckAccessRight(actionName, controllerDescriptor.ControllerName))
            {
                return false;
            }

            return true;
        }
    }
}

Now in my View I will add its namespace and then use it:


@using TestCustomHelper.Html


@Html.ActionLinkAuthorized("Create New", "Create", new { org = ViewBag.OrgBranchID }, new { @id = "linkCreateEmployee" },true) 

Cheers! and Happy Coding