Intro
In my private programming, I usually use .NET Core.
But I also use .NET Framework in my work.
I want to write at least ASP.NET MVC is the same for .NET Core and the .NET Framework.
So I try ASP.NET Framework this time.
Environments
- Visual Studio 2019 Community
- .NET Framework ver.4.8
Base Project
I create a project with Empty template.
Because there are no any class files, so I can't even open the root page(localhost:59522).
Routing
I can define how to route by "RouteConfig.cs".
First, I add "ASP.NET MVC" with NuGet.
- ASP.NET MVC ver.5.2.7
As same as ASP.NET Core, I can use "Convention-Based Routing" and "Attribute-Based Routing".
Because I felt second one was easier to use, I choosed it.
RouteConfig.cs
using System.Web.Mvc;
using System.Web.Routing;
namespace NetFrameworkSample
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Use Attribute-Based Routing
routes.MapMvcAttributeRoutes();
}
}
}
Use RouteConfig
Because it is not activated automatically, I create Global Application Class(asax) and add RouteConfig.
Global.asax
<%@ Application Codebehind="Global.asax.cs" Inherits="NetFrameworkSample.Global" Language="C#" %>
Global.asax.cs
using System;
using System.Web.Mvc;
using System.Web.Routing;
namespace NetFrameworkSample
{
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
}
Although "Global.asax.cs" has many methods by default, I only use "Application_Start" in this time.
Add a Controller class
Now I can use "Attribute-Based Routing".
So I add a Controller class and show "Hello World!".
ProductsController.cs
using System.Web.Mvc;
namespace NetFrameworkSample.Controllers
{
public class ProductsController: Controller
{
public ProductsController()
{
}
[Route("")]
public string GetMessage()
{
return "Hello world!";
}
}
}
Starting with "/"
In "Route" attribute, I can't start with slash like "[Route("/")]" or I get an exception.
I got a little confused, because I don't get any exceptions in ASP.NET Core.
Directory name
I add new route.
ProductsController.cs
...
[Route("Products")]
public string GetProductsMessage()
{
return "Hello Products";
}
}
}
Of cource I can get "Hello Products" with "localhost:59522/Products".
And I add "Products" directory and "IProductService.cs" into it.
After that, I access "localhost:59522/Products" and get an exception.
It is as same as before I add "RouteConfig".
Because if there is a directory what is named the same name as route, ASP.NET Framework searches view files in the directory.
So I have to be careful the directory names.
(I also can set routes like "localhost:59522/Api/Products")
Log (NLog)
I output log with NLog.
- NLog
- GitHub - NLog/NLog.Web: NLog integration for ASP.NET & ASP.NET Core 1-3
- Tutorial · NLog/NLog Wiki · GitHub
Install
- NLog.Web ver.4.9.3
Configurations
To use NLog in ASP.NET Framework, I add configurations in Web.config.
Web.config
...
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="NLog" type="NLog.Web.NLogHttpModule, NLog.Web" />
</modules>
</system.webServer>
</configuration>
And I add nlog.config as same as .NET Core.
nlog.config
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true">
<targets>
<target xsi:type="Console" name="outputconsole"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />
<target xsi:type="File" name="outputfile" fileName="C:\tmp\logs\NetFrameworkSample\${date:format=yyyy}\${date:format=MM}\${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="outputconsole" />>
<logger name="Microsoft.*" maxLevel="Info" final="true" />
<logger name="*" minlevel="Debug" writeTo="outputfile" />
</rules>
</nlog>
Create instances
I can create an instance by "LogManager.GetCurrentClassLogger()".
ProductsController.cs
using System.Web.Mvc;
using NLog;
namespace NetFrameworkSample.Controllers
{
public class ProductsController: Controller
{
private readonly Logger _logger;
public ProductsController()
{
_logger = LogManager.GetCurrentClassLogger();
}
[Route("")]
public string GetMessage()
{
_logger.Debug("Hello");
return "Hello world!";
}
...
Now I can output logs like below.
2020-09-02 21:05:58.0307||DEBUG|NetFrameworkSample.Controllers.ProductsController|Hello |url: http://localhost/|action:
DI (Dependency Injection)
ASP.NET Framework doesn't have DI by default.
I use Unity Container in this time.
I found I also could use "Microsoft.Extensions.DependencyInjection".
So in the future, I may try it.
Install
- Unity.Container ver.5.11.8
- Unity.Mvc ver.5.11.1
Register dependencies
IProductsService.cs
namespace NetFrameworkSample.Products
{
public interface IProductsService
{
}
}
ProductsService.cs
namespace NetFrameworkSample.Products
{
public class ProductsService: IProductsService
{
}
}
UnityConfig.cs
using System;
using Unity;
using NetFrameworkSample.Products;
namespace NetFrameworkSample
{
/// <summary>
/// Specifies the Unity configuration for the main container.
/// </summary>
public static class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container =
new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
container.RegisterType<IProductsService, ProductsService>(TypeLifetime.Scoped);
return container;
});
...
Inject
As same as "Microsoft.Extensions.DependencyInjection", Unity Container also use constructor injection.
ProductsController.cs
using System.Web.Mvc;
using NetFrameworkSample.Products;
namespace NetFrameworkSample.Controllers
{
public class ProductsController: Controller
{
private readonly IProductsService _product;
public ProductsController(IProductsService product)
{
_product = product;
}
...
Register instance
When I want to inject specify instances like DbContext, I can use "RegisterInstance".
var sample = new ProductsService();
container.RegisterInstance<IProductsService>(sample, InstanceLifetime.PerContainer);
Though I can inject NLog instance. but I shouldn't do that.
Because all of the class names of "logger" becomes "UnityConfig".
Type(Instance) lifetime
Unity Container has more types of lifetime controls than "Microsoft.Extensions.DependencyInjection".
Inject concrete classes
I can inject concrete classes without registration.
But their instances' life time is Transient.
So I must register explicit the classes what should be set other lifetime like DbContext(Scoped).
Top comments (0)