Wednesday, May 22, 2019

Injecting Service into Asp.Net Core View

In the previous posts we saw on how register a service Dependency Injection in the startup and inject the service to the MVC controller or Action method. In some cases we might need to inject a service directly into the View. A typical example is populating dropdown lists in the view.

If a view has dropdowns we cannot use the original Entity model since it will not contain the option values for the dropdown lists, in these cases we will create a custom View Model with will contain the properties from the entity model and additional lists to populate the dropdowns in the view. By injecting services to the view directly we can avoid this by injecting services directly to the view to populate the dropdown option values and continue using the entity model to display the model properties.

To inject a service directly to a view we need to use the @Inject directive. The syntax for the @Inject directive is as follows.

@inject <type> <name>

Let us create a service UserOptionsService which will provide methods to populate dropdown lists directly in the View. The service will have 2 methods

GetGenders() – Will return a static list of string with Gender values.
GetCountries() – Will return a list of country objects populated from EF Core context object.

Below is the code for the service class.

    public class UserOptionsService : IUserOptionsService
    {
        private readonly UserRegistrationContext _context;

        public UserOptionsService(UserRegistrationContext context)
        {
            _context = context;
        }
        //
        public List<string> GetGenders()
        {
            return new List<string>() { "Female", "Male" };
        }
        //
        public List<Country> GetCountries()
        {
           return _context.Country.ToListAsync().Result;
        }
    }

Once the service is ready we need to register the service in the startup so that we can use them directly in the view. Register the service in the Startup as follows.

        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddDbContext<UserRegistrationContext>(options => options.UseSqlServer(Configuration.GetConnectionString("UserRegistrationDatabase")));
            //
            services.AddScoped<IUserService, UserService>();
            services.AddTransient<UserOptionsService>();
        }

Notice that we are registering this service directly without mapping the interface since we will use this service directly in the View. The other service UserService which we used in the controller was registered using the interface since we used the service in the controller. Next we can use the service in the View as follows and call the methods in the service to populate dropdowns in the View.

@model HelloMVC.Models.EFCoreModel.Users
@using HelloMVC.Service
@inject UserOptionsService Options
@{
    ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>Users</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="FirstName" class="control-label"></label>
                <input asp-for="FirstName" class="form-control" />
                <span asp-validation-for="FirstName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="LastName" class="control-label"></label>
                <input asp-for="LastName" class="form-control" />
                <span asp-validation-for="LastName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label class="control-label">Gender</label>
                @Html.DropDownList("Gender", Options.GetGenders().Select(g =>
                    new SelectListItem() { Text = g, Value = g }))
            </div>
            <div class="form-group">
                <label asp-for="Phone" class="control-label"></label>
                <input asp-for="Phone" class="form-control" />
                <span asp-validation-for="Phone" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Email" class="control-label"></label>
                <input asp-for="Email" class="form-control" />
                <span asp-validation-for="Email" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Address" class="control-label"></label>
                <input asp-for="Address" class="form-control" />
                <span asp-validation-for="Address" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label class="control-label">Country</label>
                @Html.DropDownList("Country", Options.GetCountries().Select(c =>
                  new SelectListItem() { Text = c.Name, Value = c.CountryId.ToString()}))
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

Build and run the project, the output will be as follows. Notice that the Dropdown list controls are populated with options from the Injected Service.




Search Flipkart Products:
Flipkart.com

No comments: