Showing posts with label Razor. Show all posts
Showing posts with label Razor. Show all posts

How to add\pre-fill https://www. to input fields with type URL?

This is quick post for something I had to implement today. It's related to input fields with type="url".

What did I do?

Opened Visual Studio Code on the Views folder of a large ASP.NET MVC project and then searched for asp-for=(.*)URL using Regular Expression. That linked me to all the places (Razor .cshtml views) which had a @model (Model\ViewModel) class which happens to have an URL property.

Some of those Model\ViewModel properties didn't have the [Url] data annotation. I proceeded to add it to properties where it was missing. This data annotation is responsible for correctly generating the <input type="url" ... > on the HTML when using Razor's html helpers like this for example:

<input asp-for="Organization.URL" class="form-control">
It'll generate this HTML code:

<input class="form-control"
type="url"
data-val="true"
data-val-url="The URL field is not a valid fully-qualified http, https, or ftp URL."
id="Organization_URL"
name="Organization.URL"
value="">
With that in place I crafted some jQuery\JavaScript code that does the magic:

/**
* For all inputs with type URL and which are empty,
* we add https://www. when the input has focus.
*/
function addHttpsWwwToInputTypeUrl() {
$("input[type='url'][value='']").focus(function () {
$(this).val('https://www.')
});
}
The code is self-explanatory. It selects all inputs with type="url" and which are empty. Once the input gets focus, https://www. is added automatically to the input's value. The user now only has to complete the URL address. No more typing https://www. everytime.

The only thing necessary now is to call this JavaScript function in a central place so that it can be applied everywhere in your project.

That's it... a simple but nice user experience to have in your app. Hope it helps.

Using the power of Razor Views embedded in external class library with FluentEmail

Just got this working and would like to share how to get it configured since I could not find an explanation anywhere.

FluentEmail - All in one email sender for .NET and .NET Core is a great library to send e-mails.

Currently I have a full .NET 4.7.2 Console Application that makes use of FluentEmail.
My desire with it was to store the e-mail template (
Razor .cshtml view) in an external class library and be able to use this view\template in the Console Application.

FluentEmail GitHub page has a sample code that shows how to consume that:


var email = new Email(bob@hotmail.com)
    .Subject("Hey cool name!")
    .UsingTemplateFromEmbedded("Example.Project.Namespace.template-name.cshtml",
        new { Name = "Bob" },
        TypeFromYourEmbeddedAssembly.GetType().GetTypeInfo().Assembly);

Steps:

1 - Create a Razor Class Library project. More on that can be found here:
Create reusable UI using the Razor Class Library project in ASP.NET Core
It uses .NET Standard 2.0 as its Target framework.

2 - Add Microsoft.AspNetCore.Mvc.Core NuGet package to the class library.
This is to have Intellisense, etc in Visual Studio.

Install-Package Microsoft.AspNetCore.Mvc.Core -Version 2.1.3

3 - Add a Razor view called EmailTemplate.cshtml to your class library.

4 - Right click it in Solution Explorer and select Properties. In Build Action, select Embedded resource.

5 - Add the following code to your Razor View:


@model dynamic
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Some Title</title>
    <base href="/" />
@*<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
      <link href="css/site.css" rel="stylesheet" />
      <script src="_framework/blazor.webassembly.js"></script>*@
</head>
<body>
    E-mail template
    Hey @Model.Name,<br>
    <font size="14">You are so @Model.Compliment.</font>
</body>
</html>
Note that I’m using dynamic in the view code. This is just for testing. You can have full blown Models and use them in the templates as well.

6 - In your Console Application add a reference to the Class Library created in step 1.

7 - In your FluentEmail code, do the following in UsingTemplateFromEmbedded method:

email.To(configuration["emailTo"])
     .SetFrom(configuration["emailFrom"])
     .Subject(configuration["emailSubject"])
     .UsingTemplateFromEmbedded(
      "YourCompany.YourRazorClassLibrary.EmailTemplate.cshtml",
    new { Name = "Leniel Maccaferri", Compliment = "Cool" },
    Assembly.Load("YourCompany.YourRazorClassLibrary"));


The first parameter is the full class library (DLL) name + dot + Razor view name with .cshtml extension. The second parameter is the anonymous type that will be passed as the Model to the view and the third parameter is the class library assembly itself.


You're good to go!

This gives you a lot of flexibility.

You can add images, customize the HTML, CSS, have
Layout pages, etc.


Hope it helps.

ResourceManager with External Localization Assembly

As a software developer I like to work with everything that is related to software Localization known as L10n. Besides being a developer working defining the architecture that will be adopted in a given project and doing the hard “FUN” work writing the code, I’m also a translator if you don’t know it yet.

One thing I've been trying to do recently is to be able to use localized strings that are present in an external assembly [ DLL ] using the ResourceManager object.
I have localized strings in resource [ .resx ] files that are specific for each locale I support. I place these .resx files in a separate class library project to maintain things organized.

So, suppose the namespace of this class library is MyProject.L10n and the .resx file name is Localization.resx. This gives me access to a class named Localization within the code. I also have Localization.pt.resx. I support English and Portuguese locales in my project for now. This naming pattern allows me to have in the future a file called Localization.es-ES.resx for Castilian Spanish (as written and spoken in Spain) and another one called Localization.es-AR.resx for Argentine Spanish. During runtime the .NET framework will select the correct .resx file to extract the localized string from based on the current culture the user has set while browsing my website.

After adding a reference to this class library, I'm able to use this code in my ASP.NET MVC project in a Razor view:

MyProject.L10n.Localization.LocalizedString;

This works as expected, but it's not what I need, though. As you see the localized string key [ LocalizedString ] is hard coded. I want to be able to use the method GetString from the ResourceManager object so that I can write code like this:

ResourceManager.GetString(item.DynamicLocalizedStringValue);

The problem and the catchy here is that in order to use the resource manager the way I want, I have to point it to the external assembly this way:

grid.Column(
columnName: "Type",
header: Localization.Type,format: (item) => new ResourceManager("MyProject.L10n.Localization", typeof(Localization).Assembly).GetString(item.Type.ToString()))

This part does the tricky: typeof(Localization).Assembly

In the code block above I’m using WebGrid that is a new helper that comes with ASP.NET MVC 3. It simplifies the task of rendering tabular data. When I do item.Type.ToString() I’m actually getting different values for each row of my grid and I pass this dynamic value to ResourceManager that in return gives me the translated/localized version of a give string key.

Going even further I’ve implemented a Razor’s Helper method in a file called Helpers.cshtml and placed such file inside the App_Code folder. This is the helper’s code:

@using System.Resources
@using MyProject.L10n

@helper GetLocalizedString(string stringValue)
{
    ResourceManager rm = new ResourceManager("MyProject.L10n.Localization", typeof (Localization).Assembly);

    @rm.GetString(stringValue);
}

Now it’s just a matter of calling the helper this way in whatever place/view I need it:

grid.Column(
columnName: "Type",
header: Localization.Type,
format: (item) => @Helpers.GetLocalizedString(item.Type.ToString()))

The above code is way more clear than the one I showed your before…

Hope this post helps shed some light in this subject since the only thing that should be done is to get a reference to the assembly that holds the Localization class and pass it to the ResourceManger’s constructor.