2021年9月6日 星期一

FluentValidation 一個Model多個驗證方式

.Net Core驗證方式FluentValidation通常都會用以下方式
新增一個Validator Class,撰寫驗證要輸入的欄位
public XXXValidator()
{      
  RuleFor(x => x.xxxfiled).NotEmpty().WithMessage("請輸入欄位");          
}

DI注入Service
services.AddTransient<IValidator<AAAViewModel>, XXXValidator>();         

然後前端驗證
FluentValidation.Results.ValidationResult vResult = this._xxxValidator.Validate(model);
if (!vResult.IsValid)
{
  throw new Exception(Function_ModelStateError.FormatToString(vResult));
}        

但是如果有另一個Service也是要用AAAViewModel但是驗證的欄位不一樣呢?
先新增一個Class如下
//來源https://stackoverflow.com/questions/11607476/two-validators-for-one-model
public static class ValidationExtensions
{
     public static FluentValidation.Results.ValidationResult ValidateModel<TModel, TValidator>(this TModel model, TValidator validator, ModelStateDictionary modelState)
         where TModel : class
         where TValidator : AbstractValidator<TModel>
     {
         var result = validator.Validate(model);
         return result;
     }
}

新增另一個Validator Class,撰寫驗證要輸入的欄位
public YYYValidator()
{      
  RuleFor(x => x.yyyfiled).NotEmpty().WithMessage("請輸入欄位");          
}

DI注入另一個Service
services.AddTransient<IValidator<AAAViewModel>, YYYValidator>();         

然後前端驗證
FluentValidation.Results.ValidationResult vResult = model.ValidateModel(new YYYValidator(), ModelState);//修改這
if (!vResult.IsValid)
{
  throw new Exception(Function_ModelStateError.FormatToString(vResult));
}        

參考來源
Two Validators for one Models

2021年8月6日 星期五

Lambda Filter Detail

常常忘記這語法所以來記錄一下
情境個人資料內有許多經歷或是學歷
某天人資部需求想撈出那些人是碩士及博士
通常資料表會這樣開
員工資料主檔
public class Staff
{
	public int StaffId { get; set; }
	public string Name { get; set; }
	public List EducationList { get; set; }//多種學歷	
}
學歷檔
public class Education
{
	public int EducationId { get; set; }
	public int EducationType { get; set; }//假設有另一個資料表紀錄ID的意思 碩士是6 博士是7
	public string SchoolName { get; set; }
}
抓取過濾碩士博士
int[] filter = new int[] { 6, 7 };
result = result.Where(x => x.EducationList.Any(y => filter.Contains(y.EducationType))).ToList();

2021年3月30日 星期二

.Net Core EF Core Power Tools

之前有篇文章有寫到.Net Core 問題4 DB First後來發現另一個VS套件可以使用
1.先至官網安裝EF Core Power Tools
2.在專案上右鍵EF Core Power Tools
3.點選Add Database Connection
4.填寫連線內容(跟Framework的模型很像吧)
5.選擇Table 或其他DB功能
6.Scaffold-DbContext
Context name:輸入您要的(預設都自動帶出)
Namespace:輸入您要的(預設都自動帶出)
EntityType path:您要存放的路徑資料夾, 例如你想放在專案下的Models資料夾裡就輸入Models
...中間略可不設定用預設比較好
Pluralize or signularize generated object names:將產生的物件名稱複數化或單數化",設定為"勾選"時 後面多出"s"
Use table and column names directly from the database:使用資料表原始名稱(CX_Name沒打勾時會變成CxName)跟之前的-use-database-names一樣
Use DataAnnotation attributes to configure the model:
Custiomize code using Handlebars templates
Include connection string in generated code:連線字串放於Context中建議不勾
Install the EF Core provider pageage in the project
參考來源
EF Core Power Tools

2021年2月3日 星期三

Bootstrap 問題 找不到popper.js

Bootstrap4.5.3使用了bootstrap-select 或是bootstrap-multiselect都會遇到下面問題
Uncaught TypeError: Bootstrap's dropdowns require Popper.js
collapse.js:363 Uncaught TypeError: u is not a constructor
缺少了Popper.js檔可至cdn下載所需的但目前版本v2.x以上好像也不行
使用popper.js 1.16.1的話是可以的
參考來源
https://stackoverflow.com/questions/60837918/dropdown-js186-uncaught-typeerror-u-is-not-a-constructor-returning-when-i-clic
Bootstrap 4 error “Bootstrap dropdown require Popper.js”, with Aurelia CLI and Require.js

2021年1月14日 星期四

.Net Core 問題7 HTTP ERROR 413.1 - Request Entity Too Large

目前在寫一個.net core上傳
ok這都很簡單網路上一堆code
Html
<form enctype="multipart/form-data" method="post" asp-controller="FileStream" asp-action="Upload">
    多選檔案:<input type="file" name="File" multiple  />    <input type="submit" value="上傳" />
</form>
Controller
private IWebHostEnvironment _hostingEnvironment;
private readonly IFunction_Error _functionerror;
public FileStreamController(IWebHostEnvironment environment, IFunction_Error functionerror)
{
  _hostingEnvironment = environment;            
}
public IActionResult Index()
{
  return View();
}

[HttpPost]       
public async Task Upload(List file)
{       
  string uploadfolder = Path.Combine(_hostingEnvironment.WebRootPath, "files");      
  foreach (IFormFile item in file)
  {
   if (item.Length > 0)
   {
     string filePath = Path.Combine(uploadfolder, item.FileName);
     using (Stream fileStream = new FileStream(filePath, FileMode.Create))
     {
       await item.CopyToAsync(fileStream);
     }
   }
  }
 return View();
 }
Ok很簡單吧
User:我今天上傳了80MB的檔案出現了以下問題
好吧只好找解法了大概如下
1.Program加入
 serverOptions.Limits.MaxRequestBodySize = long.MaxValue;
 ...
 
2.startup加入
services.Configure(options =>
{
  options.MultipartBodyLengthLimit = long.MaxValue;
  ....
});
 
3.Controller加入
 [DisableRequestSizeLimit]
 
以上三種都沒用最後註解掉
看到一篇加入一個web.config程式碼如下
居然通了80MB上傳沒問題
一直以為.net core是沒web.conifg的
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="2147483647" />
      </requestFiltering>
    </security>
  </system.webServer>
</configuration>
User說:剛剛上傳了150MB的檔案都沒出現錯誤但檔案又沒傳上去
發現List<IFormFile> file是null但後端是有收到
感覺是大小沒問題只不過設定上有些不正確
接著就將startup那段註解的加了回去終於不null了
services.Configure(options =>
{
  options.BufferBodyLengthLimit = long.MaxValue;
  options.KeyLengthLimit = int.MaxValue;
  options.MultipartBodyLengthLimit = long.MaxValue;
  options.MultipartBoundaryLengthLimit = int.MaxValue;
  options.ValueCountLimit = int.MaxValue;
  options.ValueLengthLimit = int.MaxValue;
});
注意上面的MaxValue要修正阿不要真的那麼大還是要依專案來設定
參考來源
.net core issues: 413 Request Entity Too Large nginx
Kestrel web server implementation in ASP.NET Core [资源分享].netcore 部署时遇到413 Request Entity Too Large 和 413Payload Too Large 的问题 asp.net core 3.0 解除文件上传大小限制,500.30、413、api-post-form方法拿不到参数 解决方案 How to increase file upload size in ASP.NET Core https://www.aspsnippets.com/Articles/ASPNet-Core-IFormFile-always-returns-NULL.aspx .Net Core IFormFile 始终为空的问题