iT邦幫忙

3

.Net Core MVC 6.0建構紀錄

  • 分享至 

  • xImage
  •  

這篇文章主要紀錄目前自己將網站的分類方式與檔案內容做簡單紀錄並分享
採用MVC並將業務邏輯層(Service)與資料層(Repository)抽象
網站本體以"WebSite"為基底 名稱
有切分為幾個專案

1.WebSite網站本體

網站主體有幾個重要檔案

  • appsetting.json
    放置參數檔、資料庫連線字串

  • Program.cs
    註冊各種網站啟動時的內容

  • 資料庫連線註冊

builder.Services.AddDbContext<WebSiteContext>(options =>
{
    var Connect = builder.Configuration["ConnectionStrings:WebSiteConnectString"];
    options.UseSqlServer(builder.Configuration["ConnectionStrings:WebSiteConnectString"], sqlServerOptionsAction: sqlOptions => {
        sqlOptions.EnableRetryOnFailure();
    });
});
  • quartz排程套件註冊
builder.Services.AddQuartz(quartz =>
{
    quartz.UseMicrosoftDependencyInjectionJobFactory();

	var SyncWebSiteJobKey = new JobKey("WebSiteJob", "SyncWebSiteGroup");
	quartz.AddJob<SyncWebSiteJob>(opts =>
	{
		opts.WithIdentity(SyncWebSiteJobKey);
		opts.StoreDurably();
	});
	//觸發器
	quartz.AddTrigger(opts =>
	{
		opts.ForJob(SyncWebSiteJobKey);
		opts.WithIdentity("SyncWebSiteTrigger", "SyncWebSiteGroup");
		//opts.WithCronSchedule("0 0 1 * * ?").
		opts.WithCronSchedule("0 55 0 * * ?").
		WithDescription("SyncWebSite 凌晨0點55分");
	});
    builder.Services.AddQuartzHostedService(options => options.WaitForJobsToComplete = true);
}
  • DI註冊
    根據要注入的Service與Reposiotry做註冊
    如果有根據產品對象不同而邏輯不同的狀況,可以根據appsetting,在網站啟動時設定注入不同Service
//DI註冊
//WebSite Entity
builder.Services.AddScoped<IWebSiteService, WebSiteService>();
builder.Services.AddScoped<IWebSiteRepository, WebSiteRepository>();
  • autoMap註冊
builder.Services.AddAutoMapper(typeof(MappingProfile).Assembly);
  • Session時間註冊
builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromHours(2);
    options.Cookie.HttpOnly = false;
    options.Cookie.IsEssential = true;
});
  • 錯誤處理註冊
ErrorHandler.RegistEenumError<CommonError>();
 /// <summary>
 /// 註冊錯誤代碼
 /// </summary>
 /// <typeparam name="TEnum"></typeparam>
 public static void RegistEenumError<TEnum>() where TEnum : struct, Enum
 {
     var enums = Enum.GetValues(typeof(TEnum));
     var Type = typeof(TEnum);
     foreach (int item in enums)
     {
         CustomError customError = new CustomError();
         customError.ErrorCode = item;
         string? name = Enum.GetName(Type, item);
         var displayAttribute = Type.GetMember(name!)
         .First()
         .GetCustomAttribute<DisplayAttribute>();
         if (displayAttribute is not null)
         {
             customError.Message = displayAttribute!.Name ?? "未定義錯誤顯示名稱,請洽網站管理員";
         }

         if (CustomErrors.Exists(x => x.ErrorCode == customError.ErrorCode && x.Message == customError.Message))
         {
             continue;
         }
         CustomErrors.Add(customError);
     }
 }
  • WebApplication 註冊
var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
	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.UseSession();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
	name: "default",
	pattern: "{controller=Login}/{action=Login}/{id?}");


//API Route
app.MapControllerRoute(
    name: "api",
    pattern: "api/{controller=LineIndex}/{action=Login}/{id?}");

app.Run();

2.DTO 資料轉換模型

就是拿來放DTO檔案的,通常會參照資料庫格式複製同名DTO以便AutoMapper做轉換
會在Program.cs註冊MappingProfile

在DTO專案底下放置註冊檔
屬性名稱轉換 如果屬性名稱相同,AutoMapper會嘗試直接轉換

    public class MappingProfile : Profile
    {
        public MappingProfile()
        {
            //WebSite
            CreateMap<WebSite, WebSiteDTO>();
            CreateMap<WebSiteDTO, WebSite>();
         }
     }
  • 下拉選單轉換
     
     CreateMap<WebSite, SelectListItem>().
     ForMember(x => x.Text, y => y.MapFrom(o => o.Name)).
     ForMember(x => x.Value, y => y.MapFrom(o => o.DepartmentId));
  • 特殊條件轉換
 CreateMap<WebSiteRow, WebSiteDTO>()
.ForMember(x => x.CustomInternalID, opt => opt.MapFrom<WebSiteIDResolver>());

public class WebSiteResolver : IValueResolver<WebSiteRow, WebSiteDTO, int>
{
    public int Resolve(WebSiteRow source, WebSiteDTO destination, int destMember, ResolutionContext context)
    {
    return source.Basic.Entity?.SearchValue?.InternalId != null ? int.Parse(source.Basic.Entity.SearchValue.InternalId) : 0;
    }
}

3.Entity 資料庫模型

因為我是用Code First
所以會有Entitys與Migration資料夾

4.Interfaces

放置兩個資料夾Services、Repositorys
處理各個Service與Repository的介面定義放置

5.Repository

定義各個table的資料倉儲以及定義unitOfWork
基本上共通Function會有一個BaseRepository去處理
沒有太特殊的資料取得通常不太會需要特別增加Reposiotory取資料的方法

 public  class WebSiteRepository:BaseRepository<WebSite>, IWebSiteRepository
 {
     private readonly WebSiteContext _db;
     public WebSiteRepository(WebSiteContext db) : base(db)
     {
         _db = db;
     }
 }
  • BaseRepository 定義通用CRUD方法
public abstract class BaseRepository<T> : IBaseRepository<T> where T : class
{
    private JSContext _db;

    protected BaseRepository(JSContext db)
    {
        _db = db;
    }

    public void Create(T entity)
    {
        _db.Set<T>().Add(entity);
    }
    public IEnumerable<T> GetByPageList(Expression<Func<T, bool>> filter, PageList pageList, string[] includes =null,string[] orderbyDesc = null)
{
    List<T> result;
    IQueryable<T> query = _db.Set<T>();
    if (includes!=null)
    {
        foreach (string include in includes)
        {
            query = (IQueryable<T>)query.Include(include);
        }
    }

    if (filter != null)
    {
        query = query.Where(filter);
    }
    
	if (orderbyDesc != null && orderbyDesc.Length > 0)
	{
		string orderByClause = string.Join(", ", orderbyDesc.Select(p => p + " descending"));

		query = query.OrderBy(orderByClause);
	}

	var TotalObject = query.ToList();

    result = PickPageList(pageList, TotalObject);
    return result;
}

    public void SaveChanges()
    {
    _db.SaveChanges();
    }
}

6.Service

放置業務邏輯層
通常建構子會注入需要用到的Repository 如果多個table操作寫入則使用UnitOfWork
讀取則使includes 去關聯相關資料

7.ViewModel

供給View資料顯示的Model
請注意ViewModel一定不會有Entity的引用,必定都是轉換為DTO才傳遞

以上為基本.NetCore 6 專案基本架構紀錄分享 如有更詳細或是更好的方式請分享留言於底下


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言