ASP.NET Core Migration

Introduction

CMS version 1 was created based on ASP.NET Standard; in a short time, CMS migrated to ASP.NET Core; therefore, CMS version 2 is based on ASP.NET Core. This CMS uses the CodeBehind framework; this framework is an infrastructure whose executable files are aspx that run on ASP.NET Core.

The migration of this CMS from .NET Standard version 4.5 to .NET Core version 7.0 took only two weeks.

Note. Web development in the CodeBehind framework is based on a modern MVC structure and has nothing to do with Microsoft's Web Form.

An example of .NET Standard code changes to .NET Core

View in ASP.NET Standard

<%@ Page Language="C#" CodeBehind="Default.aspx.cs" Inherits="elanat.SiteEmail" %>

View in ASP.NET Core

<%@ Page Controller="Elanat.SiteEmailController" Model="Elanat.SiteEmailModel" %>

As you can see, only the first line of the aspx page information has changed, and the rest of the data has remained unchanged.

Model in ASP.NET Standard

public class SiteEmailModel

Model in ASP.NET Core

public partial class SiteEmailModel : CodeBehindModel

CodeBehind namespace has been added in the model section class; also, the word partial has been added before the class name. The parent class name of CodeBehindModel is also added in front of the model class name.

Controller in ASP.NET Standard

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace elanat
{
    public partial class SiteEmail : System.Web.UI.Page
    {
        public SiteEmailModel model = new SiteEmailModel();

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(Request.Form["btn_SendEmail"]))
                btn_SendEmail_Click(sender, e);

            if (string.IsNullOrEmpty(Request.Form["hdn_ContentId"]))
            {
                if (string.IsNullOrEmpty(Request.QueryString["content_id"]))
                    return;

                if (!Request.QueryString["content_id"].IsNumber())
                    return;

                model.ContentIdValue = Request.QueryString["content_id"].ToString(); ;
            }

            model.SetValue();

            // Set Required Field Validation
            model.SetImportantField();
        }

        protected void btn_SendEmail_Click(object sender, EventArgs e)
        {
            model.ContentIdValue = Request.Form["hdn_ContentId"];
            model.YourEmailValue = Request.Form["txt_YourEmail"];
            model.RecipientsEmailValue = Request.Form["txt_RecipientsEmail"];
            model.CaptchaTextValue = Request.Form["txt_Captcha"];


            // Evaluate Field Check
            model.EvaluateField(Request.Form);
            if (model.FindEvaluateError)
            {
                ResponseForm rf = new ResponseForm(StaticObject.GetCurrentSiteGlobalLanguage());

                foreach (string EvaluateError in model.EvaluateErrorList)
                    rf.AddLocalMessage(EvaluateError, "problem");

                rf.RedirectToResponseFormPage();
            }

            if (!model.CaptchaTextValue.MatchByCaptcha())
            {
                model.CaptchaIncorrectErrorView();
                return;
            }

            model.SendEmail();
            model.SuccessView();
        }
    }
}

Controller in ASP.NET Core

using CodeBehind;

namespace Elanat
{
    public partial class SiteEmailController : CodeBehindController
    {
        public SiteEmailModel model = new SiteEmailModel();

        public void PageLoad(HttpContext context)
        {
            if (!string.IsNullOrEmpty(context.Request.Form["btn_SendEmail"]))
            {
                btn_SendEmail_Click(context);
                return;
            }

            if (string.IsNullOrEmpty(context.Request.Form["hdn_ContentId"]))
            {
                if (string.IsNullOrEmpty(context.Request.Query["content_id"]))
                {
                    IgnoreViewAndModel = true;
                    return;
                }

                if (!context.Request.Query["content_id"].ToString().IsNumber())
                {
                    IgnoreViewAndModel = true;
                    return;
                }

                model.ContentIdValue = context.Request.Query["content_id"].ToString(); ;
            }

            model.SetValue();

            // Set Required Field Validation
            model.SetImportantField();

            View(model);
        }

        protected void btn_SendEmail_Click(HttpContext context)
        {
            model.ContentIdValue = context.Request.Form["hdn_ContentId"];
            model.YourEmailValue = context.Request.Form["txt_YourEmail"];
            model.RecipientsEmailValue = context.Request.Form["txt_RecipientsEmail"];
            model.CaptchaTextValue = context.Request.Form["txt_Captcha"];


            // Evaluate Field Check
            model.EvaluateField(context.Request.Form);
            if (model.FindEvaluateError)
            {
                ResponseForm rf = new ResponseForm(StaticObject.GetCurrentSiteGlobalLanguage());

                foreach (string EvaluateError in model.EvaluateErrorList)
                    rf.AddLocalMessage(EvaluateError, "problem");

                rf.AddReturnFunction("el_SetWarningField('" + model.WarningFieldClassList.SplitText("$") + "', '" + model.WarningFieldClassList.SplitValue("$") + "')");

                rf.RedirectToResponseFormPage();

                IgnoreViewAndModel = true;

                return;
            }


            if (!model.CaptchaTextValue.MatchByCaptcha())
            {
                model.CaptchaIncorrectErrorView();

                View(model);

                return;
            }

            model.SendEmail(context);

            model.SuccessView();

            View(model);
        }
    }
}

Controller section changes have also been done simply.

The following are the controller changes:

Added CodeBehind namespace.

System.Web.UI.Page has been removed, and CodeBehindController has been added instead.

The underline of the main method has been remove(Page_Load to PageLoad).

The main method has been changed from private to public.

The following input arguments were omitted.

object sender, EventArgs e

The following new argument is added.

HttpContext context

View(model) method; Added before the end of the main method

To access the current HttpContext, the HttpContext context argument has been added inside the btn_SendEmail_Click method.

Added context prefix to Request

Please note that the capitalization of the first letter of the project name and the addition of Controller to the name of the MemberChangeEmail class is for arranging the naming and is not required!

We created some methods that were in standard .NET but not in .NET using Extension methods, and the codes remained intact.

Example of SaveAs method on IFormFile.

public static void SaveAs(this IFormFile PostedFile, string FilePath)
{
    using (Stream TmpFileStream = new FileStream(FilePath, FileMode.Create, FileAccess.ReadWrite))
    {
             PostedFile.CopyTo(TmpFileStream);
    }
}

Fortunately, all the data remained unchanged, and the source code of the server side also had minor changes; For example, the App_Data directory remains as a relic of the ASP.NET standard.

The CMS repository based on ASP.NET Core can be seen in the link below

https://github.com/elanatframework/Elanat

CMS external add-on repository

https://github.com/elanatframework/Elanat_add-ons

Code-Behind library is a backend framework

https://github.com/elanatframework/Code_behind

CMS old

We created a new repository and copied all the information from the ASP.NET Standard-based CMS repository into the new repository. This repository's README.md file provides information on how to migrate CMS  from ASP.NET Standard to ASP.NET Core.

You can see the CMS repository based on ASP.NET Standard in the link below.