Posts

....
Technical Blog for .NET Developers ©

Showing posts with label mvc. Show all posts
Showing posts with label mvc. Show all posts

Saturday, October 14, 2017

MVC4 Multi-language

Application Resources can be created in ASP.NET applications with two different scopes, depending on the level you want to share these resources across the application

In this example we will create a set of global resources containing dictionaries for the application display in three different languages: English (en), Spanish (es), and Catalán (ca)



The application we will build is a data-entry form based on Guest model, and will be displayed in the selected language


    public class Guest
    {
        [Required(ErrorMessageResourceType = typeof(Resources.Dictionary), 
         ErrorMessageResourceName="RequiredFirstName")]
        public string FirstName { get; set; }

        [Required(ErrorMessageResourceType = typeof(Resources.Dictionary), 
         ErrorMessageResourceName = "RequiredLastName")]
        public string LastName { get; set; }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:d}")]
        public DateTime? BirthDate { get; set; }
    }




We will add the next div element to the _layout.cshtml view in order to generate the language selector


    <div class="content-wrapper">
        @{
            CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
            string selectedLanguageStyle = "background-color:#FFDAA3;font-weight:bold;";
            <div class="float-right">                        
            @switch (currentCulture.TwoLetterISOLanguageName)
            {
                case "en":
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "en-US" })'>English</a>
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "es-ES" })'>Spanish</a>
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "ca-ES" })'>Catalán</a>
                    break;
                case "es":
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "en-US" })'>English</a>
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "es-ES" })'>Spanish</a>
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "ca-ES" })'>Catalán</a>
                    break;
                case "ca":
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "en-US" })'>English</a>
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "es-ES" })'>Spanish</a>
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "ca-ES" })'>Catalán</a>
                    break;
            }
            </div>
        }
    </div>


This is the action method called from the language selectors (anchor elements), inside the HomeController


    public ActionResult ChangeLanguage(string culture)
    {
        Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);
        Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture;

        Session["lang"] = culture;

        return Redirect(Request.UrlReferrer.ToString());
    }


The approach is this: we will create a BaseController to handle the ExecuteCore method, and stablish the thread's current culture. ExecuteCore method invokes the action in the current controller context. The controllers in our application will inherit BaseController


    public class BaseController : Controller
    {
        //
        // GET: /Base/

        protected override void ExecuteCore()
        {
            var culture = Session["lang"] ?? "en-US";        

            Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture.ToString());
            Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture;

            base.ExecuteCore();
        }

        protected override bool DisableAsyncSupport
        {
            get { return true; }
        }
    }


DysableAsyncSupport property gets whether to disable the asynchronous support for the controller. This flag is for backwards compatibility. ASP.NET MVC 4. allows a controller to support asynchronous patterns. This means ExecuteCore doesn't get called on derived classes. Derived classes can override this flag and set to true if they still need ExecuteCore to be called

The strongly-typed view based on Guest model is this:


@model MvcApp1.Models.Guest

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>@Resources.Dictionary.ViewTitle</h2>

<div>
    @using (Html.BeginForm())
    {
        @Html.ValidationSummary(true)
        <table>
            <tbody>
                <tr>
                    <td>
                        <div class="editor-field">
                            <span>@Resources.Dictionary.FirstName</span>
                        </div>                        
                    </td>
                    <td>
                        @Html.EditorFor(model => model.FirstName)
                        @Html.ValidationMessageFor(model => model.FirstName)                        
                    </td>
                </tr>
                <tr>
                    <td>
                        <div class="editor-field">
                            <span>@Resources.Dictionary.LastName</span>
                        </div>                        
                    </td>
                    <td>
                        @Html.EditorFor(model => model.LastName)
                        @Html.ValidationMessageFor(model => model.LastName)                        
                    </td>
                </tr>
                <tr>
                    <td>
                        <div class="editor-field">
                            <span>@Resources.Dictionary.BirthDate</span>
                        </div>                        
                    </td>
                    <td>
                        @Html.EditorFor(model => model.BirthDate)
                    </td>
                </tr>
            </tbody>
        </table>
        <input type="submit" value="Save"/>
    }    
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}


The result is the next:




<METHOD SOFTWARE © 2014>

Monday, January 2, 2017

MVC4 Ajax Forms

ASP.NET MVC 4 includes Ajax functionalities based on jQuery javascript library. Most of the Ajax features in the framework build on or extend features in jQuery

In this post we will implement an asynchronous request form with validation

This is the Chemical model in our Application

 
    public class ChemicalElement
    {
        public int IdElement { get; set; }

        [DisplayName("Name")]
        [Required]
        public string Name { get; set; }

        [DisplayName("Latin name")]
        [Required]
        public string LatinName { get; set; }

        [DisplayName("Symbol")]
        [Required]
        [RegularExpression(@"\b[a-zA-Z]{1,3}\b")]
        public string Symbol { get; set; }
    }
        


We have imported the next SQL schema (table and stored procedure)



The code to release the search of chemical elements is the next


    public PartialViewResult SearchChemicalElements(string search)
    {
        var elementsModel = SearchElementsModel(search);

        return PartialView("Elements", elementsModel);
    }

    private IEnumerable<ChemicalElement> SearchElementsModel(string search)
    {
        var allElements = Elements.SearchElements(search);

        return allElements;
    }
        


And in the Elements class the implementation of the SearchElement method is this

   
	public static IEnumerable<ChemicalElement> SearchElements(string search)
    {
        using (CHEMICALSEntities context = new CHEMICALSEntities())
        {
            ObjectResult<SearchElementsBySymbol_Result> matchElements =
                context.SearchElementsBySymbol("%" + search + "%");

            foreach (var element in matchElements)
                yield return new ChemicalElement()
                {
                    IdElement = element.IdElement,
                    Name = element.Name,
                    LatinName = element.LatinName,
                    Symbol = element.Symbol
                };
        }
    }
        


The code in the View to make the process work asynchronously, is the next


@using (Ajax.BeginForm("SearchChemicalElements", "Chemical", new AjaxOptions
    {
        InsertionMode = InsertionMode.Replace,
        HttpMethod = "GET",
        LoadingElementId = "preloader",
        UpdateTargetId = "searchResults",
    }))
        


This code renders an html form with the next marks



The information about how to perform the AJAX request is contained in the DOM, and it is released by the jquery.unobtrusive-ajax.js code

The PartialView for Elements is strongly typed and renders a table in a loop for each element



The validation rules are specified in the model, so the code in the view

 
@Html.TextBoxFor(m => m.Symbol, new { Name = "search"})


will renders the information into these data dash attributes


data-val="true" 
data-val-regex="The field Symbol must match the regular expression '\b[a-zA-Z]{1,3}\b'." 
data-val-regex-pattern="\b[a-zA-Z]{1,3}\b" 
data-val-required="The field Symbol is required." 
id="Symbol" name="search"
    


The Ajax request, and validation are implemented inside the jQuery scripts

  
  @section scripts {
    <script type="text/javascript" src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
    <script type="text/javascript" src="~/Scripts/jquery.validate.min.js"></script>
    <script type="text/javascript" src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
}