European ASP.NET MVC Hosting

BLOG about Latest ASP.NET MVC Hosting and Its Technology - Dedicated to European Windows Hosting Customer

ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: ActionResult In ASP.NET Core MVC

clock January 20, 2021 08:56 by author Peter
This article is an  overview of the use of ActionResult in ASP.Net Core MVC. ASP.NET Core MVC has different types of Action Results. Each action result returns a different format of the output. As a programmer, we need to use different action results to get the expected output. 

What is Action Method in ASP.NET Core MVC?
Actions are the methods in controller class which are responsible for returning the view or Json data. Action will mainly have return type “ActionResult” and it will be invoked from method InvokeAction called by controller. All the public methods inside a controller which respond to the URL are known as Action Methods. When creating an Action Method we must follow these rules. I have divided all the action methods into the following categories:

  1. ActionResult
  2. RedirectActionResult
  3. FileResult
  4. Security

Miscellaneous Action Results

Action Method
Description
IActionResult
Defines a contract that represents the result of an action method.
ActionResult
A default implementation of IActionResult.
ContentResult
Represents a text result.
EmptyResult
Represents an ActionResult that when executed will do nothing.
JsonResult
An action result which formats the given object as JSON.
PartialViewResult
Represents an ActionResult that renders a partial view to the response.
ViewResult
Represents an ActionResult that renders a view to the response.
ViewComponentResult
An IActionResult which renders a view component to the response.

ActionResult
The IActionResult return type is appropriate when multiple ActionResult return types are possible in an action. IActionResult and ActionResult work as a container for other action results, in that IActionResult is an interface and ActionResult is an abstract class that other action results inherit from.

public IActionResult Index()  
{  
      return View();  

ActionResult
ActionResult is the base class of all the result type action method.

public ActionResult About()  
{  
     return View();  

ContentResult
ContentResult represents a text result. The default return type of a ContentResult is string, but it’s not limited to string. We can return any type of response by specifying a MIME type, in the code.

public ContentResult ContentResult()  
{  
      return Content("I am ContentResult");  
}  

EmptyResult
EmptyResult represents an ActionResult that when executed will do nothing. We can use it when we want to return empty result.

public EmptyResult EmptyResult() 
  
      return new EmptyResult();  

JsonResult
JsonResult formats the given object as JSON. JsonResult is use to return JSON-formatted data, it returns JSON regardless of what format is requested through Accept header. There is no content negotiation when we use JsonResult.
public JsonResult JsonResult()  
{  
      var name = "Farhan Ahmed";  
      return Json(new { data=name});  
}  

PartialViewResult
PartialViewResult represents an ActionResult that renders a partial view to the response. PartialViews are essential when it comes to loading a part of page through AJAX, they return raw rendered HTML.


public PartialViewResult PartialViewResult()  
{  
      return PartialView("_PartialView");  
}  

ViewResult
ViewResult represents an ActionResult that renders a view to the response. It is used to render a view to response, we use it when we want to render a simple .cshtml view.

public ViewResult ViewResult()  
{  
      return View("About","Home");  
}  

ViewComponentResult
ViewComponentResult is an IActionResult which renders a view component to the response. We use view component by calling Component.InvokeAsync in the view. We can use it to return HTML form a view component. If we want to reuse our business logic or refresh the HTML parts of the page that are loaded with view component we can do that using view component.

public ViewComponent ViewComponent()  
{  
       return ViewComponent();  

Action results from previous version of ASP.NET MVC that are either renamed or deleted.
  • JavaScriptResult - This action result does not exist anymore we can use ContentResult.
  • FilePathResult - We can use VirtualFileResult or PhysicalFileResult instead of FilePathResult
  • HttpNotFoundResult - We can use NotFoundResult instead HttpNotFoundResult
  • HttpStatusCodeResult - We can use StatusCodeResult instead HttpStatusCodeResult
  • HttpUnauthorizedResult - We can use UnauthorizedResult instead HttpUnauthorizedResult


ASP.NET MVC 6 Hosting - HostForLIFEASP.NET :: Redirect Action Result in ASP.NET Core MVC

clock January 15, 2021 08:56 by author Peter

This article overviews redirect action results in ASP.NET Core MVC. We will lean all redirect action results step by step with examples.

There are four types of redirect action results in ASP.Net Core MVC. Each one can either return normal redirect or permanent. The return method related to the permanent one is suffixed with the Permanent keyword. You can also return these results with their Permanent property set to true. These action results are:
    RedirectResult
    RedirectToActionResult
    RedirectToRouteResult
    LocalRedirectResult

RedirectResult
RedirectResult is an ActionResult that returns a Found (302), Moved Permanently (301), Temporary Redirect (307), or Permanent Redirect (308) response with a Location header to the supplied URL. It will redirect us to the provided URL, it doesn’t matter if the URL is relative or absolute.
    public RedirectResult MyProfile()  
    {  
       return Redirect("https://www.c-sharpcorner.com/members/farhan-ahmed24");  
    }  
      
    public RedirectResult Profile()  
    {  
       return RedirectPermanent("https://www.c-sharpcorner.com/members/farhan-ahmed24");  
    }  


If we call the RedirectPermanent method, it redirect us permanently. Also as I explained in previous section we don’t need to use these methods to redirect permanently or temporarily, we can just new up an instance of RedirectResult with its Permanent property set to true or false and return that instead.
    return new RedirectResult("/") { Permanent = true};  

RedirectToActionResult

RedirectToActionResult is an ActionResult that returns a Found (302), Moved Permanently (301), Temporary Redirect (307), or Permanent Redirect (308) response with a Location header. It targets a controller action, taking in action name, controller name, and route value.
    public RedirectToActionResult EmployeeList()  
    {  
        return RedirectToAction("Index", "Employees");  
    }  


RedirectToRouteResult
RedirectToRouteResult is an ActionResult that returns a Found (302), Moved Permanently (301), Temporary Redirect (307), or Permanent Redirect (308) response with a Location header. Targets a registered route. It should be used when we want to redirect to a route. It takes a route name, route value and redirect us to that route with the route values provided.
    public RedirectToRouteResult DepartmentList()  
    {  
        return RedirectToRoute(new { action = "Index", controller = "Departments", area="" });  
    }  


LocalRedirectResult

LocalRedirectResult is an ActionResult that returns a Found (302), Moved Permanently (301), Temporary Redirect (307), or Permanent Redirect (308) response with a Location header to the supplied local URL. We should use LocalRedirectResult if we want to make sure that the redirects occur in some context that are local to our site. This action result type takes a string for URL needed for redirect, and a bool flag to tell it if it’s permanent. Under the hood, it checks the URL with the Url.IsLocalUrl("URL") method to see if it’s local. If it redirects us to the address, but if it wasn’t, it will throw an InvalidOperationException. You cannot pass a local URL with an absolute address like this, http://localhost:52513/Home/Index, you’ll get an exception. That’s because the IsLocalUrl method considers a URL like this to not be local, so you must always pass a relative URL in.
    public LocalRedirectResult LocalRedirect()  
    {  
        return LocalRedirect("/Home/Index");  
    }  

    public LocalRedirectResult LocalRedirectActionResult()  
            {  
                var IsHomeIndexLocal = Url.IsLocalUrl("/Home/Index");  
                var isRootLocal = Url.IsLocalUrl("/");  
      
                var isAbsoluteUrlLocal = Url.IsLocalUrl("http://localhost: 52513/Home/Index");  
                return LocalRedirect("/Home/Index");  
            }  

Step 1
Open Visual Studio 2019 and select the ASP.NET Core Web Application template and click Next.
 
Step 2
Name the project FileResultActionsCoreMvc_Demo and click Create.
 
Step 3
Select Web Application (Model-View-Controller), and then select Create. Visual Studio used the default template for the MVC project you just created.
 
Step 4
In Solution Explorer, right-click the wwwroot folder. Select Add > New Folder. Name the folder Files. Add some files to work with them.
 
Complete controller code
    using System;  
    using System.Collections.Generic;  
    using System.Diagnostics;  
    using System.Linq;  
    using System.Threading.Tasks;  
    using Microsoft.AspNetCore.Mvc;  
    using Microsoft.Extensions.Logging;  
    using RedirectResultActionsCoreMvc_Demo.Models;  
      
    namespace RedirectResultActionsCoreMvc_Demo.Controllers  
    {  
        public class HomeController : Controller  
        {  
            public IActionResult Index()  
            {  
                return View();  
            }  
      
            public RedirectResult MyProfile()  
            {  
                return Redirect("https://www.c-sharpcorner.com/members/farhan-ahmed24");  
            }  
            public RedirectResult Profile()  
            {  
                return RedirectPermanent("https://www.c-sharpcorner.com/members/farhan-ahmed24");  
            }  
      
            public RedirectToActionResult EmployeeList()  
            {  
                return RedirectToAction("Index", "Employees");  
            }  
      
            public RedirectToRouteResult DepartmentList()  
            {  
                return RedirectToRoute(new { action = "Index", controller = "Departments", area="" });  
            }  
      
            public LocalRedirectResult LocalRedirect()  
            {  
                return LocalRedirect("/Home/Index");  
            }  
        }  
    }  


Step 5
Open Index view which is in the views folder under the Home folder. Add the below code in Index view.
 
Index View
    @{  
        ViewData["Title"] = "Home Page";  
    }  
      
    <h3 class="text-uppercase">RedirectResult Action in core mvc</h3>  
    <ul class="list-group list-group-horizontal">  
        <li class="list-group-item"><a asp-action="MyProfile" asp-controller="Home" target="_blank">Redirect Result</a></li>  
        <li class="list-group-item"><a asp-action="EmployeeList" asp-controller="Home" target="_blank">RedirectToActionResult</a></li>  
        <li class="list-group-item"><a asp-action="DepartmentList" asp-controller="Home" target="_blank">RedirectToRouteResult</a></li>  
        <li class="list-group-item"><a asp-action="LocalRedirect" asp-controller="Home" target="_blank">LocalRedirectResultt</a></li>  
    </ul>  

Step 6

Build and run your Project, ctrl+F5



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Learn About Filters In ASP.NET MVC

clock December 30, 2020 12:17 by author Peter

As part of this article, we will learn about ASP.Net MVC filters, their different types and we will create a custom log Action Filter using Visual Studio. So without wasting any time let's start.

What are ASP.Net MVC filters
In an ASP.Net MVC Web application, we have action methods defined in controllers that call from different views. For example, when the user clicks on some button on the view, a request goes to the designated controller and then the corresponding action method. Within this flow, sometimes we want to perform logic either before an action method is called or after an action method runs.
 
To fulfill the above condition ASP.Net MVC provides us filters. Filters are the custom classes that provide us with an option to add pre-action and post-action behavior to controller action methods.
 
ASP.NET MVC framework supports four different types of filters:

  • Authorization filters
  • Action filters
  • Result filters
  • Exception filters

Note
They are executed in the order listed above.
 
Authorization filters
In ASP.NET MVC web application by default, all the action methods of all the controllers can be accessible for all the users (for both authenticated and anonymous users both). For this, if we want to restrict some action methods from anonymous users or we want to allow the action methods only to an authenticated user, then you need to use the Authorization Filter in MVC.
 
The Authorization Filter provides two built-in attributes such as Authorize and AllowAnonymous. We can decorate our action methods with the Authorize attribute which allows access to the only authenticated user and we can use AllowAnonymous attribute to allow some action method to all users.
 
We can also create custom Authorization filters for this we have to implement IAuthenticationFilter interface and have overrides its OnAuthentication() and OnAuthenticationChallenge(). We are going deep into it.
 
Action filters
In the ASP.NET MVC web application, action filters are used to perform some logic before and after action methods. The output cache is one of the built-in action filters which we can use in our action methods.
    [OutputCache(Duration=100)]
    public ActionResult Index()
    {
       return View();
    }

We can also create a custom action filter either by implementing IActionFilter interface and FilterAttribute class or by deriving the ActionFilterAttribute abstract class. As part of this article, I am covering creating a custom action filter using the ActionFilterAttribute abstract class.
 
ActionFilterAttribute includes the following method to override it:
    void OnActionExecuted(ActionExecutedContext filterContext)
    void OnActionExecuting(ActionExecutingContext filterContext)
    void OnResultExecuted(ResultExecutedContext filterContext)
    void OnResultExecuting(ResultExecutingContext filterContext)

We will see this in detail below.
 
Result filters
 
In an ASP.NET MVC web application, result filters are used to perform some logic before and after a view result is executed. For example, we might want to modify a view result right before the view is rendered.
 
Exception filters
 
In the ASP.NET MVC web application, we can use an exception filter to handle errors raised by either our controller actions or controller action results. We also can use exception filters to log errors.
 
Creating a Log Action Filter
Open Visual Studio and create a new ASP.NET Web Application

Choose Empty, select “MVC” and then click the OK button.

Add a ‘Filters’ folder and create a new class LogActionFilter.cs under it:
    using System.Diagnostics;  
    using System.Web.Mvc;  
    using System.Web.Routing;  
      
    namespace FiltersMVC.Filters  
    {  
        public class LogActionFilter : ActionFilterAttribute  
      
        {  
            public override void OnActionExecuting(ActionExecutingContext filterContext)  
            {  
                Log("OnActionExecuting", filterContext.RouteData);  
            }  
      
            public override void OnActionExecuted(ActionExecutedContext filterContext)  
            {  
                Log("OnActionExecuted", filterContext.RouteData);  
            }  
      
            public override void OnResultExecuting(ResultExecutingContext filterContext)  
            {  
                Log("OnResultExecuting", filterContext.RouteData);  
            }  
      
            public override void OnResultExecuted(ResultExecutedContext filterContext)  
            {  
                Log("OnResultExecuted", filterContext.RouteData);  
            }  
      
      
            private void Log(string methodName, RouteData routeData)  
            {  
                var controllerName = routeData.Values["controller"];  
                var actionName = routeData.Values["action"];  
                var message = $"{methodName} controller:{controllerName} action:{actionName}";  
                Debug.WriteLine(message, "Action Filter Log");  
            }  
        }  
    }  


We overrides OnActionExecuting(), OnActionExecuted(), OnResultExecuting(), and OnResultExecuted() methods all are calling the Log() method. The name of the method and the current route data is passed to the Log() method. The Log() method writes a message to the Visual Studio Output window.
 
Now, add HomeController.cs under the Controllers folder.
    using FiltersMVC.Filters;  
    using System.Web.Mvc;  
      
    namespace FiltersMVC.Controllers  
    {  
        [LogActionFilter]  
        public class HomeController : Controller  
        {  
            // GET: Home  
            public ActionResult Index()  
            {  
                return View();  
            }  
        }  
    }  

After adding the above files our folder structure will look like this:


Now run the application, we can see the results in the “Output” window.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Ajax.ActionLink and Html.ActionLink in MVC

clock December 16, 2020 08:26 by author Peter

In this article, you will learn the use of the Ajax.ActionLink helper and Html.ActionLink. I will compare both to show you how they differ. Okay, let's begin with Html.ActionLink.

Html.ActionLink
Html.ActionLink creates a hyperlink on a view page and the user clicks it to navigate to a new URL. It does not link to a view directly, rather it links to a controller's action. Here are some samples of Html.ActionLink.
 
If you want to navigate to the same controller's action method, use the one given below. Razor is smart enough to assume the first param is link text and the second param is the action method name, if it finds only two parameters.
    @Html.ActionLink("Click here", // <-- Link text  
                     "Index" // <-- Action Method Name  
                     )  

It's rendered HTML: <a href="/">Click here</a>
 
If you want to navigate to a different controller's action method, use the one given below. You can even avoid typing "null" for the route value and htmlArguments. Here also, razor will assume the first param as link text, the second param as the action method name and the third param as the controller name, if it finds three parameters.
    @Html.ActionLink("Click here", // <-- Link text  
                     "About", // <-- Action Method Name  
                     "Home", // <-- Controller Name  
                     null, // <-- Route value  
                     null // <-- htmlArguments  
                     )  


It's rendered HTML: <a href="/Home/About">Click here</a>
 
If you want to navigate to the same controller's action method then use the one given below. Here razor will assume the first param is link text, second param is an action method and the third param is the route value. We can avoid typing "null" for the htmlArgument; that works fine.
    @Html.ActionLink("Edit", // <-- Link text  
                     "Edit", // <-- Action Method Name  
                     new { id=item.CustomerID }, // <-- Route value  
                     null // <-- htmlArguments  
                    )  


It's rendered HTML: <a href="/Home/Edit/187">Edit</a>
 
If you want to navigate to the same controller's action method then use the one given below. Here razor will assume the first param is link text, second param is the action method and the third param is the route value. Instead of typing "null" or avoiding the htmlAttribute, I am using the "class" attribute with "ui-btn" as the name.
    @Html.ActionLink("Edit", // <-- Link text  
                     "Edit", // <-- Action Method Name  
                     new { id=item.CustomerID }, // <-- Route value  
                     new {@class="ui-btn"} // <-- htmlArguments  
                    )  

It's rendered HTML: <a class="ui-btn" href="/Home/Edit/187">Edit</a>
 
What if one wants rendered HTML to be as given below that is an application-specific anonymous attribute:
<a class="ui-btn" data-val="abc" href="/Home/Edit/ANTON">Edit</a>
 
If you try to do it as given below, you will get the error:

The reason is that we can't use an anonymous property/attribute having a dash in the name. Use an underscore instead of a dash and MVC will automatically replace the underscore with a dash in the rendered HTML, here it is:
    @Html.ActionLink("Edit", // <-- Link text  
                     "Edit", // <-- Action Method Name  
                     new { id=item.CustomerID }, // <-- Route arguments  
                     new {@class="ui-btn", data_val="abc"} // <-- htmlArguments  
                    )  

That's how we work around in MVC for any anonymous property.
 
Note: You can notice that Html.ActionLink takes at least two parameters as Html.ActionLink(LinkText, ActionMethod).
 
Ajax.ActionLink

Ajax.ActionLink is much like the Html.ActionLink counterpart, it also creates the hyperlink <a href="">Click here</a> but when the user clicks it and has a JavaScript enabled browser, Ajax.ActionLink sends the asynchronous request instead of navigating to the new URL. With the Ajax.ActionLink we specify what controller's action method is to be invoked and also specify what to do with the response coming back from the action method.
 
Let's create an Ajax.ActionLink helper that will send an asynchronous request to the action method and will update the DOM with the result.
 
Step 1
At first we need an Ajax.ActionLink that will send the async request, so here we go:
    <h2>Customers</h2>  
    @Ajax.ActionLink("Customer from Germany", // <-- Text to display  
                     "Germany", // <-- Action Method Name  
                     new AjaxOptions  
                     {  
                         UpdateTargetId="CustomerList", // <-- DOM element ID to update  
                         InsertionMode = InsertionMode.Replace, // <-- Replace the content of DOM element  
                         HttpMethod = "GET" // <-- HTTP method  
                     })  
    @Ajax.ActionLink("Customer from Mexico", // <-- Text to display  
                     "Mexico", // <-- Action Method Name  
                     new AjaxOptions  
                     {  
                         UpdateTargetId="CustomerList", // <-- DOM element ID to update  
                         InsertionMode = InsertionMode.Replace, // <-- Replace the content of DOM element  
                         HttpMethod = "GET" // <-- HTTP method  
                     })  
    <div id="CustomerList"></div>  
    @section scripts{  
        @Scripts.Render("~/Scripts/jquery.unobtrusive-ajax.min.js")  
    }  


In the code above, you can see that I have created two Ajax.ActionLinks, one to display the list of customers from Germany and another to display the list of customers from Mexico, all will be called asynchronously. We have not specified which controller to access, so by default it will look in the same controller. Here is the generated HTML by both Ajax.ActionLink.
<a data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#CustomerList" href="/Home/Germany">Customer from Germany</a>
 
<a data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#CustomerList" href="/Home/Mexico">Customer from Mexico</a>
 

The unobtrusive jQuery uses the data-ajax prefix for JavaScript to invoke action methods on the server rather than intrusively emitting inline client scripts.
 
When we will click the link it will make a GET HTTP method call and the returned result will be updated to a DOM element by Id "CustomerList".
 
Always remember to place a reference of the jquery.unobtrusive-ajax.js library file after jquery-{version}.js file references, we can use bundling also. If you don't include the jquery.unobtrusive-ajax.js or do it incorrectly, then when you click the link to the view list of countries, an async result will be opened on the new browser tab.
 
Also, ensure that the unobtrusive JavaScript is enabled in your web.config (it should be by default).
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />  

Step 2
Now, let's go ahead and implement the "Germany" and "Mexico" action methods that will return a PartialView.
    NorthwindEntities db = new NorthwindEntities();  
    public PartialViewResult Germany()  
    {  
        var result = from r in db.Customers  
                        where r.Country == "Germany"  
                        select r;  
        return PartialView("_Country", result);  
    }  
    public PartialViewResult Mexico()  
    {  
        var result = from r in db.Customers  
                        where r.Country == "Mexico"  
                        select r;  
        return PartialView("_Country", result);  
    }  


So, in both of the PartialViewResult methods I have used a LINQ query that will filter records on country and then pass the results to a partial view page "_Country.cshtml". I have placed this file in the "Shared" folder so that any view can access it. Let's move on to see the partial view page "_Country.cshtml".
 
Step 3
I made this view page strongly typed by using @model and then iterated through the model data to create a nice tabular format.
    @model IEnumerable<MvcActionLink.Models.Customer>  
    <table>  
        <tr>  
            <th>  
                @Html.DisplayNameFor(model => model.ContactName)  
            </th>  
            <th>  
                @Html.DisplayNameFor(model => model.Address)  
            </th>  
        </tr>  
    @foreach (var item in Model) {  
        <tr>  
            <td>  
                @Html.DisplayFor(modelItem => item.ContactName)  
            </td>  
            <td>  
                @Html.DisplayFor(modelItem => item.Address)  
            </td>  
        </tr>  
    }  
    </table>  


Now, you all set to run the application.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Simple Insert And Select Operation Using .NET Core MVC With ADO.NET And Entity Framework Core

clock December 2, 2020 08:53 by author Peter

In this article, I am going to show you guys how to use ADO.NET and Entity framework core in .NET Core MVC. This way you can use either both or on way to implement your application as per your requirements. I attached the project solution which you can refer to. Also, I have shown a repository pattern to complete this project.

Step 1
I have used MS SQLServer for the database.
    USE [CrudDB]  
    GO  
    /****** Object: Table [dbo].[Crud_Data] Script Date: 22-11-2020 09:33:14 ******/  
    SET ANSI_NULLS ON  
    GO  
    SET QUOTED_IDENTIFIER ON  
    GO  
    CREATE TABLE [dbo].[Crud_Data](  
    [id] [int] IDENTITY(1,1) NOT NULL,  
    [Name] [varchar](50) NULL,  
    [City] [varchar](50) NULL,  
    [InsertDate] [datetime] NULL,  
    [FatherName] [varchar](50) NULL,  
    CONSTRAINT [PK_Crud_Data] PRIMARY KEY CLUSTERED  
    (  
    [id] ASC  
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]  
    ) ON [PRIMARY]  
    GO  


Step-2
Change in the startup.cs file in the project root
    public void ConfigureServices(IServiceCollection services)  
         {  
             services.AddControllersWithViews();  
             //By changing the service reference we are switching to ado.net  to entity framwork core vice versa  
             //----Start  
             services.AddScoped<ICrudRepository, CrudRepository>();  
             //services.AddScoped<ICrudRepository, CrudContextRepository>();  
             //-----End  
             services.AddDbContext<DBAccessContext>(options => options.UseSqlServer(Configuration.GetConnectionString("MyKey")));  
         }  

Step 3
Connection string in appsettings.json:
    {  
      "Logging": {  
        "LogLevel": {  
          "Default": "Information",  
          "Microsoft": "Warning",  
          "Microsoft.Hosting.Lifetime": "Information"  
        }  
      },  
      "AllowedHosts": "*",  
      "ConnectionStrings": {  
        "MyKey": "Data Source=PRO-ACQER8AM;Initial Catalog=CrudDB;Integrated Security=True;"  
      }  
    }

Step 4
Made model to communicate with View and DB Layer.
    namespace TestDemo.Models  
    {  
        [Table("Crud_Data", Schema = "dbo")]  
        public class CrudModel  
        {  
            public int Id { get; set; }  
            [Required]  
            public string Name { get; set; }  
            [Required]  
            public string City { get; set; }  
      
            public DateTime? InsertDate { get; set; }  
               
            public string? FatherName { get; set; }  
        }  
    } 

Step 5
Controller class CrudController.cs with dependency injection use with helps to lose coupling while switching from ADO.NET to Entity framework and vice-versa.
    public class CrudController : Controller  
       {  
           private readonly ICrudRepository crudRepository;  
           public CrudController(ICrudRepository crudRepository)  
           {  
               this.crudRepository = crudRepository;  
           }  
           public IActionResult Index()  
           {  
               ViewBag.ModelList = crudRepository.GetData();  
               return View();  
           }  
           [HttpPost]  
           public IActionResult Index(CrudModel crudModel)  
           {  
               try  
               {  
                   if (ModelState.IsValid)  
                   {  
                       // ICrudRepository crudRepository = new CrudRepository();  
                       var result = crudRepository.insert(new string[] { crudModel.Name, crudModel.City, System.DateTime.Now.ToString(), crudModel.FatherName });  
                       ViewBag.ModelList = crudRepository.GetData();  
                       if (result)  
                       {  
                           ViewBag.Msg = "Succeed";  
                           ViewBag.alertType = "alert alert-success";  
                       }  
                       else  
                       {  
                           ViewBag.Msg = "Insertion failed";  
                           ViewBag.alertType = "alert alert-danger";  
                       }  
      
                   }  
               }  
               catch (Exception ex)  
               {  
                   ViewBag.Msg = "Insertion failed";  
                   ViewBag.alertType = "alert alert-danger";  
                   ModelState.AddModelError("Message", ex.Message);  
               }  
      
               return View();  
      
           }  
       }

 

Step 6
The project consists of class files for the DB layer and Repository folder and one partial view for showing the detail view.
    We have created an interface in the repository folder to make a service and use both the classes as a service.
    We have created the DBLayer folder and created 2 classes one consists of ado.net insert and select the method and another one for Entity framework Core DBContext.
    In Partial View, I have injected the service directly so that you no need to pass the model to communicate with a partial view. you can check the getdata() method by debugging and uncommenting the specific section over there.
    System.Data.sqlclient reference required to use ado.net, you can add this by using NuGet package manager.

DataAccessDB.cs
    public class DataAccessDB : IDataAccessDB  
       {  
           private readonly IConfiguration config;  
           string connsString = string.Empty;  
           public DataAccessDB(IConfiguration config)  
           {  
               this.config = config;  
               connsString = config.GetConnectionString("MyKey");  
           }  
           public List<CrudModel> GetData()  
           {  
               // string connsString = config.GetConnectionString("MyKey");// "Data Source=PRO-ACQER8AM;Initial Catalog=CrudDB;Integrated Security=True;";  
               List<TestDemo.Models.CrudModel> ModelList = new List<Models.CrudModel>();  
               using (SqlConnection conn = new SqlConnection(connsString))  
               {  
                   conn.Open();  
                   using (SqlCommand command = new SqlCommand($"select * from [dbo].[Crud_Data]", conn))  
                   {  
                       try  
                       {  
                           using (var result = command.ExecuteReader())  
                           {  
      
                               while (result.Read())  
                               {  
      
                                   ModelList.Add(  
                                       new Models.CrudModel { Id = (int)result.GetValue("Id"), Name = (string)result.GetValue("Name"), City = (string)result.GetValue("City"),  FatherName = (string)result.GetValue("FatherName").ToString() });  
                               }  
                           }  
                       }  
                       catch (Exception ex)  
                       {  
      
                       }  
                       finally  
                       {  
                           conn.Close();  
                       }  
      
                       return ModelList;  
                   }  
      
      
               }  
           }  
      
             
      
           public bool insert(string[] Param)  
           {  
      
               //   string connsString = config.GetConnectionString("MyKey");// "Data Source=PRO-ACQER8AM;Initial Catalog=CrudDB;Integrated Security=True;";  
      
               using (SqlConnection conn = new SqlConnection(connsString))  
               {  
                   conn.Open();  
                   using (SqlCommand command = new SqlCommand($"INSERT INTO [dbo].[Crud_Data] ([Name],[City],[InsertDate],FatherName) VALUES ('{Param[0]}','{Param[1]}',getdate(),'{Param[3]}')", conn))  
                   {  
                       try  
                       {  
                           var result = command.ExecuteNonQuery();  
      
                           if (result > 0)  
                           {  
                               return true;  
                           }  
                       }  
                       catch (Exception)  
                       {  
      
                       }  
                       finally  
                       {  
                           conn.Close();  
                       }  
                       return false;  
                   }  
      
      
               }  
      
           }  
       }  


 DBAccessContext.cs
    public class DBAccessContext:DbContext  
      {  
      
          public DBAccessContext(DbContextOptions<DBAccessContext> options):base(options)  
          {   
          }  
      
          public DbSet<CrudModel> Crud_Data { get; set; }  
      
      }  


CrudRepository.cs
    public class CrudRepository : ICrudRepository  
    {  
        private readonly IConfiguration configuration;  
        private readonly DataAccessDB DB;  
      
        public CrudRepository(IConfiguration configuration)  
        {  
            this.configuration = configuration;  
            this.DB = new DataAccessDB(configuration);   
        }  
        public List<CrudModel> GetData()  
        {  
            return DB.GetData();  
        }  
      
        public bool insert(string[] Param)  
        {  
      
            return DB.insert(Param);  
      
        }  
      
      
    }  

 CrudContextRepository.cs
    public class CrudContextRepository : ICrudRepository  
       {  
           private readonly DBAccessContext dBAccessContext;  
           private readonly IConfiguration configuration;  
      
           public CrudContextRepository(DBAccessContext dBAccessContext,IConfiguration configuration)  
           {  
               this.dBAccessContext = dBAccessContext;  
               this.configuration = configuration;  
           }  
           public  List<CrudModel> GetData()  
           {  
              return dBAccessContext.Crud_Data.ToList();  
           }  
      
           public bool insert(string[] Param)  
           {  
               var model = new CrudModel()  
               {  
                   Name = Param[0],  
                   City = Param[1],  
                   InsertDate = System.DateTime.Now,  
                   FatherName= Param[3]  
      
               };  
               
            dBAccessContext.Crud_Data.Add(model);  
              var result= dBAccessContext.SaveChanges();  
      
               if (result>0)  
               {  
                   return true;  
               }       
               return false;  
           }  
       }  

 ICrudRepository.cs
    public interface ICrudRepository  
      {  
          bool insert(string[] Param);  
          List<TestDemo.Models.CrudModel> GetData();  
      
      }  


 Index.cshtml under View/Crud/
    @model TestDemo.Models.CrudModel  
      
    <partial name="_ValidationScriptsPartial" />  
    <style>  
        .bg-secondary {  
            background-color: #f4f5f7 !important;  
        }  
    </style>  
      
    <h1>Welcome to Crud</h1>  
      
    <form id="Form1" method="post" asp-action="Index" asp-controller="Crud" >  
        @if (ViewBag.Msg != null)  
        {  
      
            <div class="@ViewBag.alertType" role="alert">  
                <div asp-validation-summary="All">@ViewBag.Msg</div>  
            </div>  
            @*<script>  
                    $(function () {  
      
                        $.notify({  
                            title: "<strong>Message:</strong> ",  
                            message: "@ViewBag.Msg"  
                        });  
                    });  
      
                </script>*@  
      
            ViewBag.Msg = null;  
        }  
      
        <div class="card">  
            <div class="card-body">  
                <div class="form-group">  
                    <label asp-for="Name">Name</label>  
                    <input asp-for="Name" class="form-control">  
                    <span asp-validation-for="Name" class="text-danger"></span>  
                </div>  
                <div class="form-group">  
                    <label asp-for="City">City</label>  
                    <input asp-for="City" class="form-control" />  
                    <span asp-validation-for="City" class="text-danger"></span>  
                </div>  
                <div class="form-group">  
                    <label asp-for="FatherName">Father Name</label>  
                    <input asp-for="FatherName" class="form-control" />  
                    <span asp-validation-for="FatherName" class="text-danger"></span>  
                </div>  
            </div>  
            <div class="card-footer">  
                <button type="submit" class="btn btn-primary">Submit</button>  
            </div>  
        </div>  
      
        @{ if (ViewBag.ModelList != null)  
            { <div class="card">  
                    <div class="card-body">  
                        <partial name="_ListPartial" model="@ViewBag.ModelList" />  
                    </div>  
                </div>  
            }}  
      
        @*@await Html.PartialAsync("_ListPartial", Model)*@  
      
        @*@(await Html.RenderComponentAsync<TestDemo.Components.Component>(RenderMode.ServerPrerendered,null))*@  
      
    </form> 



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Display A Document From SQL Server To A Web Page In ASP.NET MVC

clock October 27, 2020 10:19 by author Peter

In this blog post, I'll discuss a useful yet easy to implement document viewer API. Using that you can display a source file (e.g. Word, Presentation, Diagram, PSD) from your server to your browser without downloading it.
 

Some Use-Cases
    Display a Word resume to a user in a web browser
    Render a Visio Diagram on the web page
    View a Presentation or a Slide online without downloading it

Implementation
 
Now as the use-cases are clear, we will dive into the API implementation. It'll be an ASP.NET MVC application. We'll pull data/documents from the database and save it to a stream. You have to specify the file format in order to render it correctly. The source document will be then rendered to HTML. Eventually, our controller will return this stream to the View/browser.  
    public ActionResult Index()  
    {  
         License lic = new License();  
         lic.SetLicense(@"D:/GD Licenses/Conholdate.Total.NET.lic");  
         MemoryStream outputStream = new MemoryStream();  
         //specify just the file name if you are pulling the data from database   
         string fileName = "sample.pdf";  
      
         FileType fileType = FileType.FromExtension(Path.GetExtension(fileName));  
      
         using (Viewer viewer = new Viewer(() => GetSourceFileStream(fileName), () => new LoadOptions(fileType)))  
         {  
               HtmlViewOptions Options = HtmlViewOptions.ForEmbeddedResources(  
                    (pageNumber) => outputStream,  
                    (pageNumber, pageStream) => { });  
               viewer.View(Options);  
         }
         outputStream.Position = 0;  
         return File(outputStream, "text/html");  
                   
    }  
    private Stream GetSourceFileStream(string fileName) =>  
                new MemoryStream(GetSourceFileBytesFromDb(fileName));  
      
    //TODO: If you want to pull the data from the DB  
    private byte[] GetSourceFileBytesFromDb(string fileName) =>  
                System.IO.File.ReadAllBytes(fileName);  


Have a look at this image/screenshot. We displayed a PDF from Server to Browser.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: ViewBag, ViewData And TempData In MVC

clock October 23, 2020 09:44 by author Peter

ViewBag, ViewData, and TempData all are objects in ASP.NET MVC and these are used to pass the data in various scenarios.

The following are the scenarios where we can use these objects.
    Pass the data from Controller to View.
    Pass the data from one action to another action in the same Controller.
    Pass the data in between Controllers.
    Pass the data between consecutive requests.

ViewBag
ViewBag is a dynamic object to pass the data from Controller to View. And, this will pass the data as a property of object ViewBag. And we have no need to typecast to read the data or for null checking. The scope of ViewBag is permitted to the current request and the value of ViewBag will become null while redirecting.
 
Ex Controller
    Public ActionResult Index()  
    {  
        ViewBag.Title = “Welcome”;  
        return View();  
    }  

View
    <h2>@ViewBag.Title</h2>  

ViewData
ViewData is a dictionary object to pass the data from Controller to View where data is passed in the form of key-value pair. And typecasting is required to read the data in View if the data is complex and we need to ensure null check to avoid null exceptions. The scope of ViewData is similar to ViewBag and it is restricted to the current request and the value of ViewData will become null while redirecting.
 
Ex
Controller:

    Public ActionResult Index()  
    {  
        ViewData[”Title”] = “Welcome”;  
        return View();  
    }  


View
    <h2>@ViewData[“Title”]</h2>  

TempData
TempData is a dictionary object to pass the data from one action to other action in the same Controller or different Controllers. Usually, TempData object will be stored in a session object. Tempdata is also required to typecast and for null checking before reading data from it. TempData scope is limited to the next request and if we want Tempdata to be available even further, we should use Keep and peek.
 
Ex - Controller
    Public ActionResult Index()  
    {  
        TempData[”Data”] = “I am from Index action”;  
        return View();  
    }  

    Public string Get()  
    {  
        return TempData[”Data”] ;  
    }  

To summarize, ViewBag and ViewData are used to pass the data from Controller action to View and TempData is used to pass the data from action to another action or one Controller to another Controller.
 
Hope you have understood the concept of ViewBag, ViewData, and TempData.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: How to Adding Robots.txt to your ASP.NET MVC Applications?

clock September 23, 2020 08:49 by author Peter

One of the things I always forgot to add to my web applications is the Robots.txt file that Search Engines use to see what they should index. This file and sitemaps help make your site easier to navigate by the bots and allow them to understand what's legal and what you'd rather not have the revealed in their engines. I usually add any administrative pages or account pages even though they're protected by security, no need for the login page to be index if they sniff the link.

So how do you add Robots.txt to your MVC application? Glad you asked, here is a little code to get you started.

Sample Code

1.  Select the controller you would like to use for the robots.txt output.  I chose the HomeController in my application as I use it for most “top level” generic links like about us, contact us, index, etc.

2. Now, create a method called Robots to handle the request.
#region -- Robots() Method --
public ActionResult Robots()
{
    Response.ContentType = "text/plain";
    return View();
}
#endregion


3. Add the Robots.cshtml view to your Controller’s View directory.  Here is the code I have in my view, yours will vary.
@{
    Layout = null;
}
# robots.txt for @this.Request.Url.Host
User-agent: *
Disallow: /Administration/
Disallow: /Account/


4. Load up the class you are using to control your routes, if you are in an Area, this could your AreaRegistration class.  If you are at the top like I am and using the standard MVC template, this is probably the Global.asax.cs file.  Add your route to this file, mine looks like this.

routes.MapRoute("Robots.txt",

                "robots.txt",

                new { controller = "Home", action = "Robots" });


5. Compile and test.

If you've got an internet facing site, the chances are you will have a bot find you're request this page. you might as well give them the benefit of the doubt and allow them to understand where you want them to go. additionally you may save yourself some error log when this page is requested and no controller is found.

Just like something in ASP.NET, there are many ways to solve this riddle, if you use a different approach, please feel free to share it in the comments.

HostForLIFE.eu ASP.NET MVC 6 Hosting
HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes. We have customers from around the globe, spread across every continent. We serve the hosting needs of the business and professional, government and nonprofit, entertainment and personal use market segments.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Display A Document From SQL Server To A Web Page In ASP.NET MVC

clock September 9, 2020 09:24 by author Peter

In this blog post, I'll discuss a useful yet easy to implement document viewer API. Using that you can display a source file (e.g. Word, Presentation, Diagram, PSD) from your server to your browser without downloading it.
 
Some Use-Cases
    Display a Word resume to a user in a web browser
    Render a Visio Diagram on the web page
    View a Presentation or a Slide online without downloading it

Implementation

Now as the use-cases are clear, we will dive into the API implementation. It'll be an ASP.NET MVC application. We'll pull data/documents from the database and save it to a stream. You have to specify the file format in order to render it correctly. The source document will be then rendered to HTML. Eventually, our controller will return this stream to the View/browser.  
    public ActionResult Index()  
    {  
         License lic = new License();  
         lic.SetLicense(@"D:/GD Licenses/Conholdate.Total.NET.lic");  
         MemoryStream outputStream = new MemoryStream();  
         //specify just the file name if you are pulling the data from database   
         string fileName = "sample.pdf";  
      
         FileType fileType = FileType.FromExtension(Path.GetExtension(fileName));  
      
         using (Viewer viewer = new Viewer(() => GetSourceFileStream(fileName), () => new LoadOptions(fileType)))  
         {  
               HtmlViewOptions Options = HtmlViewOptions.ForEmbeddedResources(  
                    (pageNumber) => outputStream,  
                    (pageNumber, pageStream) => { });  
               viewer.View(Options);  
         }
         outputStream.Position = 0;  
         return File(outputStream, "text/html");  
                   
    }  
    private Stream GetSourceFileStream(string fileName) =>  
                new MemoryStream(GetSourceFileBytesFromDb(fileName));  
      
    //TODO: If you want to pull the data from the DB  
    private byte[] GetSourceFileBytesFromDb(string fileName) =>  
                System.IO.File.ReadAllBytes(fileName);  


HostForLIFE.eu ASP.NET MVC 6 Hosting
HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes. We have customers from around the globe, spread across every continent. We serve the hosting needs of the business and professional, government and nonprofit, entertainment and personal use market segments.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Using Auto-Mapper In An ASP.NET Core MVC Application

clock August 25, 2020 08:24 by author Peter

In today’s article we will look at an extremely useful feature. In many applications, the data we collect on the user interface needs to be converted to some different form before it can be stored in the data store and vice versa. This requires some mapping logic and it is mostly done using mapping classes and logic. Today, we will look at a ready to use Nuget package to do this mapping for us and make the process amazingly simple. We will apply this mapping in an ASP.NET Core MVC application.

Creating the .NET Core MVC application
We will start by creating an ASP.NET Core 3.1 MVC application using Visual Studio 2019 community edition as below,

We select the ASP.NET Core web application and click “Next”

Next, we enter the project details and click “Create”

From the list of ASP.NET Core web applications, we select “Web Application (Model-View-Controller) and leave all other values as default.
 
We now have the ASP.NET Core MVC application created. The next step is to add the “AutoMapper” Nugget package as below,

Remember to select the latest version.

After that create three classes under the “Models” folder as below,
 
Employee.cs

    namespace WebAppAutoMapper.Models { 
        publicclassEmployee { 
            publicstring FirstName { 
                get; 
                set; 
            } 
            publicstring LastName { 
                get; 
                set; 
            } 
            publicstring StreetAddress { 
                get; 
                set; 
            } 
            publicstring City { 
                get; 
                set; 
            } 
            publicstring Province { 
                get; 
                set; 
            } 
            publicstring Country { 
                get; 
                set; 
            } 
            publicstring Email { 
                get; 
                set; 
            } 
            publicstring Phone { 
                get; 
                set; 
            } 
            publicEmployee() { 
                FirstName = "Munib"; 
                LastName = "Butt"; 
                StreetAddress = "123 Street One"; 
                City = "Toronto"; 
                Province = "Ontario"; 
                Country = "Canada"; 
                Email = "[email protected]"; 
                Phone = "+14161112222"; 
            } 
        } 
    } 

EmployeeDTO.cs

    namespace WebAppAutoMapper.Models { 
        publicclassEmployeeDTO { 
            publicstring Name { 
                get; 
                set; 
            } 
            publicstring Address { 
                get; 
                set; 
            } 
            publicstring Email { 
                get; 
                set; 
            } 
            publicstring Phone { 
                get; 
                set; 
            } 
        } 
    } 

And finally,AutoMap.cs

    using AutoMapper; 
     
    namespace WebAppAutoMapper.Models 
    { 
    publicclassAutoMap : Profile 
        { 
    publicAutoMap() 
            { 
                CreateMap<Employee, EmployeeDTO>() // means you want to map from Employee to EmployeeDTO 
                .ForMember(d => d.Name, source => source.MapFrom(s => s.FirstName + " " + s.LastName)) 
                .ForMember(d => d.Address, source => source.MapFrom(s => s.StreetAddress + ", " + s.City + ", " + s.Province + ", " + s.Country)) 
                .ForMember(d => d.Phone, source => source.MapFrom(s => s.Phone)) 
                .ForMember(d => d.Email, source => source.MapFrom(s => s.Email)); 
            } 
        } 
    } 

Here we see that we have an Employee class which has several properties. We also have an EmployeeDTO class which has fewer properties than the Employee class. Now, we want to map the values from the Employee class to the EmployeeDTO class using some mapping logic. This logic is implemented in the AutoMap.cs class which inherits from the Profile class.
 
Finally, we setup the AutoMap in the Startup.cs class in the “ConfigureServices” function as below,

    using Microsoft.AspNetCore.Builder; 
    using Microsoft.AspNetCore.Hosting; 
    using Microsoft.Extensions.Configuration; 
    using Microsoft.Extensions.DependencyInjection; 
    using Microsoft.Extensions.Hosting; 
    using AutoMapper; 
    using WebAppAutoMapper.Models; 
     
    namespace WebAppAutoMapper 
    { 
    publicclassStartup 
        { 
    publicStartup(IConfiguration configuration) 
            { 
                Configuration = configuration; 
            } 
     
    public IConfiguration Configuration { get; } 
     
    // This method gets called by the runtime. Use this method to add services to the container. 
    publicvoid ConfigureServices(IServiceCollection services) 
            { 
                services.AddAutoMapper(c => c.AddProfile<AutoMap>(), typeof(Startup)); 
                services.AddControllersWithViews(); 
            } 
     
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 
    publicvoid Configure(IApplicationBuilder app, IWebHostEnvironment env) 
            { 
    if (env.IsDevelopment()) 
                { 
                    app.UseDeveloperExceptionPage(); 
                } 
    else 
                { 
                    app.UseExceptionHandler("/Home/Error"); 
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 
                    app.UseHsts(); 
                } 
                app.UseHttpsRedirection(); 
                app.UseStaticFiles(); 
     
                app.UseRouting(); 
     
                app.UseAuthorization(); 
     
                app.UseEndpoints(endpoints => 
                { 
                    endpoints.MapControllerRoute( 
                        name: "default", 
                        pattern: "{controller=Home}/{action=Index}/{id?}"); 
                }); 
            } 
        } 
    } 

Now, all the plumbing is in place and we can use the mapping as below in the Home Controller,

    using System.Diagnostics; 
    using Microsoft.AspNetCore.Mvc; 
    using Microsoft.Extensions.Logging; 
    using WebAppAutoMapper.Models; 
    using AutoMapper; 
     
    namespace WebAppAutoMapper.Controllers 
    { 
    publicclassHomeController : Controller 
        { 
    privatereadonly ILogger<HomeController> _logger; 
    privatereadonly IMapper _mapper; 
     
    publicHomeController(ILogger<HomeController> logger, IMapper mapper) 
            { 
                _logger = logger; 
                _mapper = mapper; 
            } 
     
    public IActionResult Index() 
            { 
                Employee emp = new Employee(); 
    var empDTO = _mapper.Map<EmployeeDTO>(emp); 
    return View(); 
            } 
     
    public IActionResult Privacy() 
            { 
    return View(); 
            } 
     
            [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 
    public IActionResult Error() 
            { 
    return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); 
            } 
        } 
    } 

We can put a breakpoint at the “return View();” line in the Index function and see the Employee DTO values as below,

Here we see that the empDTO object has the values extracted and mapped from the Employee object.

HostForLIFE.eu ASP.NET MVC 6 Hosting
HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes. We have customers from around the globe, spread across every continent. We serve the hosting needs of the business and professional, government and nonprofit, entertainment and personal use market segments.

 



About HostForLIFE

HostForLIFE is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Tag cloud

Sign in