using Ds;
using Ds.Gv;
using iText.Kernel.Geom;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NPOI.SS.Formula.Functions;
using NPOI.SS.Util;
using Su;
using System.Linq.Expressions;
namespace CallCampaign.Api
{
/// <summary>
/// 行銷活動
/// </summary>
[Route("api/call-campaign")]
[ApiController]
[SetAuthorizationFilter(Sh.AuthCode.不設限)]
public class ReserveCampaignController : Controller
{
/// <summary>
/// 取得行銷活動列表
/// </summary>
/// <param name="reserveCampaignName"></param>
/// <param name="currentPage"></param>
/// <param name="pageSize"></param>
/// <param name="orderByName"></param>
/// <param name="sort"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
[HttpGet("")]
public async Task<object> ListAsync([FromQuery] string reserveCampaignName = "", [FromQuery] int? currentPage = 1, [FromQuery] int? pageSize = 20, [FromQuery] string orderByName = "OrderNo", [FromQuery] string sort = "asc")
{
if (pageSize > 500)
{
pageSize = 500;
}
if (!(sort == "asc" || sort == "desc"))
{
throw new CustomException(System.Net.HttpStatusCode.BadRequest, "sort只能是asc或desc");
}
var temp = new V_ReserveCampaign().GetType().GetProperty(orderByName);
if (temp == null)
{
throw new CustomException(System.Net.HttpStatusCode.BadRequest, "不存在欄位");
}
Expression<Func<V_ReserveCampaign, bool>> q = p => p.Is_Deleted == "N"
&& (string.IsNullOrEmpty(reserveCampaignName) || (p.ReserveCampaignName != null && p.ReserveCampaignName.Contains(reserveCampaignName)))
;
if (orderByName.ToLower().Trim() != "id")
{
orderByName += " " + sort + ", id desc";
}
else
{
orderByName += " " + sort;
}
var ct = NewContext.GvContext;
var list = await ct.GetPageListAsync(q, columns: "Id, ReserveCampaignName, OrderNo, StartAt, EndAt, ModifierName, ModifyDate, CreatorName, CreateDate", page: currentPage ?? 1, pageSize: pageSize ?? 20, orderByName);
//var list = await ct.GetPageListAsync(q, page: currentPage ?? 1, pageSize: pageSize ?? 20, orderByName + " " + sort);
return list;
}
/// <summary>
/// 取得行銷活動
/// </summary>
/// <param name="Id"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
[HttpGet("get")]
public async Task<dynamic> GetAsync([FromQuery] int Id)
{
var res = await Ds.NewContext.GvContext.ReserveCampaigns.Where(r => r.Id == Id)
.FirstOrDefaultAsync();
if (res == null)
{
throw new CustomException(System.Net.HttpStatusCode.BadRequest, "查無資料 " + Id.ToString());
}
return res;
}
/// <summary>
/// 建立行銷活動
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="CustomException"></exception>
[HttpPost("")]
public async Task<object> CreateAsync(Dtos.CreateReserveCampaign dto)
{
var ct = NewContext.GvContext;
var res = await Models.ReserveCampaignHelper.CreateReserveCampaignAsync(ct, dto);
return res;
}
/// <summary>
/// 編輯行銷活動
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="CustomException"></exception>
[HttpPatch("")]
public async Task<object> UpdateAsync(Dtos.UpdateReserveCampaign dto)
{
var ct = NewContext.GvContext;
var res = await Models.ReserveCampaignHelper.UpdateReserveCampaignAsync(ct, dto);
return res;
}
/// <summary>
/// 刪除行銷活動
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
/// <exception cref="CustomException"></exception>
[HttpDelete("")]
public async Task<object> DeleteAsync([FromQuery] int id)
{
var res = await Ds.NewContext.GvContext.MarkDeleteAsync<Ds.Gv.ReserveCampaign>(id, Sh.ModifyInfo);
return res;
}
}
}
/// <summary>
/// 取得列表
/// </summary>
/// <param name="name"></param>
/// <param name="currentPage"></param>
/// <param name="pageSize"></param>
/// <param name="orderByName"></param>
/// <param name="sort"></param>
/// <returns></returns>
[HttpGet("")]
public object List([FromQuery] string name = "", [FromQuery] int? currentPage = 1, [FromQuery] int? pageSize = 20, [FromQuery] string orderByName = "OrderNo", [FromQuery] string sort = "asc")
{
return "";
}
/// <summary>
/// 取得明細資料
/// </summary>
/// <param name="Id"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
[HttpGet("get")]
public object Get([FromQuery] int id)
{
return "";
}
/// <summary>
/// 建立
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="CustomException"></exception>
[HttpPost("")]
public object Create(Dtos.PhysicalCheckUpType dto)
{
return "";
}
/// <summary>
/// 編輯
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
/// <exception cref="CustomException"></exception>
[HttpPatch("")]
public object Update(Dtos.PhysicalCheckUpType dto)
{
return "";
}
/// <summary>
/// 刪除
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
/// <exception cref="CustomException"></exception>
[HttpDelete("")]
public object Delete([FromQuery] int id)
{
return 1;
}
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
const int durationInSeconds = 60 * 60 * 24 * 365; //一年
ctx.Context.Response.Headers[HeaderNames.CacheControl] =
"public,max-age=" + durationInSeconds;
}
});
app.UseRouting();
<configuration>
<system.webServer>
<security>
<requestFiltering>
<hiddenSegments>
<add segment=".svn" />
</hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
</configuration>
public class UploadController : ApiController
{
public async Task<object> PostFormData()
{
var provider = new MultipartMemoryStreamProvider();
if (! Request.Content.IsMimeMultipartContent())
{
return "no file";
}
//要注意這裡的 await
await Request.Content.ReadAsMultipartAsync(provider);
foreach (var content in provider.Contents)
{
if (content.Headers.ContentDisposition.FileName != null)
{
string localFilename = content.Headers.ContentDisposition.FileName.Replace("\"", "");
System.IO.Directory.CreateDirectory(HttpContext.Current.Server.MapPath(@"~/App_Data/Temp/"));
string filename = HttpContext.Current.Server.MapPath(@"~/App_Data/Temp/" + localFilename);
if (System.IO.File.Exists(filename))
{
System.IO.File.Delete(filename);
}
using (var fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write))
{
var contentStream = await content.ReadAsStreamAsync();
await contentStream.CopyToAsync(fileStream);
Trace.WriteLine("Save To" + filename);
}
}
}
return "OK";
}
}
/// <summary>
/// 檔案檢查
/// </summary>
/// <param name="actionContext"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public override async Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
Trace.WriteLine("ApiCheckFile OnActionExecutingAsync");
var request = actionContext.Request;
if (!request.Content.IsMimeMultipartContent())
{
return;
}
var provider = new MultipartMemoryStreamProvider();
await request.Content.ReadAsMultipartAsync(provider);
//把 provider 存入 System.Web.HttpContext.Current.Items 之中,以便在 controller 中再度使用
System.Web.HttpContext.Current.Items["MimeMultipartContentProvider"] = provider;
foreach (var content in provider.Contents)
{
if (content.Headers.ContentDisposition.FileName != null)
{
var filename = content.Headers.ContentDisposition.FileName.Replace("\"", "");
Trace.WriteLine(filename);
var ext = System.IO.Path.GetExtension(filename);
if (!".jpg,.jpeg,.png".Contains(ext.ToLower()))
{
throw new Exception("file format error.");
}
}
}
return;
}
public async Task<object> PostFormData()
{
//改由 HttpContext.Current.Items 中,讀取資料。
MultipartMemoryStreamProvider provider = (MultipartMemoryStreamProvider)System.Web.HttpContext.Current.Items["MimeMultipartContentProvider"];
//如果沒有經過 filter,provider會是 null, 這時就要直接由 Request.Content 讀入 provider
if (provider == null)
{
provider = new MultipartMemoryStreamProvider();
Request.Content.ReadAsMultipartAsync(provider);
}
foreach (var content in provider.Contents)
{
if (content.Headers.ContentDisposition.FileName != null)
{
string localFilename = content.Headers.ContentDisposition.FileName.Replace("\"", "");
Trace.WriteLine("FileName: " + localFilename);
Trace.WriteLine("FileName: " + @"~/App_Data/Temp/" + localFilename);
System.IO.Directory.CreateDirectory(HttpContext.Current.Server.MapPath(@"~/App_Data/Temp/"));
string filename = HttpContext.Current.Server.MapPath(@"~/App_Data/Temp/" + localFilename);
if (System.IO.File.Exists(filename))
{
System.IO.File.Delete(filename);
}
using (var fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write))
{
var contentStream = await content.ReadAsStreamAsync();
await contentStream.CopyToAsync(fileStream);
Trace.WriteLine("Save To" + filename);
}
}
else
{
var contentStream = await content.ReadAsStreamAsync();
var reader = new System.IO.StreamReader(contentStream);
var data = reader.ReadToEnd();
Trace.WriteLine("data: " + data);
}
}
return "OK";
}
public override void OnActionExecuting(ActionExecutingContext actionContext)
{
Debug.WriteLine("MvcCheckFileFilter OnActionExecuting");
if (actionContext.HttpContext.Request.Files.Count > 0)
{
for (int i = 0; i < actionContext.HttpContext.Request.Files.Count; i++)
{
System.Web.HttpPostedFileBase file = actionContext.HttpContext.Request.Files[i];
if (System.IO.Path.GetExtension(file.FileName) != ".jpg")
{
throw new Exception("file format error.");
}
Debug.WriteLine(i + "MvcCheckFileFilter OnActionExecuting File type: " + file.FileName.ToString());
}
}
//以下寫法會發生錯誤: 無法將類型 'System.String' 的物件轉換為類型 'System.Web.HttpPostedFileBase'。
//foreach (HttpPostedFileBase file in actionContext.HttpContext.Request.Files)
//{
// if (System.IO.Path.GetExtension(file.FileName) != ".jpg")
// {
// throw new Exception("file format error.");
// }
//}
}
/// <summary>
/// 取得授權的項目
/// </summary>
static string[] Scopes = { GmailService.Scope.GmailSend };
// 和登入 google 的帳號無關
// 任意值,若未來有使用者認証,可使用使用者編號或登入帳號。
string Username = "ABC";
/// <summary>
/// 存放 client_secret 和 credential 的地方
/// </summary>
string SecretPath = @"D:\project\GmailTest\Data\Secrets";
/// <summary>
/// 認証完成後回傳的網址, 必需和 OAuth 2.0 Client Id 中填寫的 "已授權的重新導向 URI" 相同。
/// </summary>
string RedirectUri = $"https://localhost:44340/Home/AuthReturn";
/// <summary>
/// 取得認証用的網址
/// </summary>
/// <returns></returns>
public async Task<string> GetAuthUrl()
{
using (var stream = new FileStream(Path.Combine(SecretPath, "client_secret.json"), FileMode.Open, FileAccess.Read))
{
FileDataStore dataStore = null;
var credentialRoot = Path.Combine(SecretPath, "Credentials");
if (!Directory.Exists(credentialRoot))
{
Directory.CreateDirectory(credentialRoot);
}
//存放 credential 的地方,每個 username 會建立一個目錄。
string filePath = Path.Combine(credentialRoot, Username);
dataStore = new FileDataStore(filePath);
IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = GoogleClientSecrets.Load(stream).Secrets,
Scopes = Scopes,
DataStore = dataStore
});
var authResult = await new AuthorizationCodeWebApp(flow, RedirectUri, Username)
.AuthorizeAsync(Username, CancellationToken.None);
return authResult.RedirectUri;
}
}
public async Task<string> AuthReturn(AuthorizationCodeResponseUrl authorizationCode)
{
string[] scopes = new[] { GmailService.Scope.GmailSend };
using (var stream = new FileStream(Path.Combine(SecretPath, "client_secret.json"), FileMode.Open, FileAccess.Read))
{
//確認 credential 的目錄已建立.
var credentialRoot = Path.Combine(SecretPath, "Credentials");
if (!Directory.Exists(credentialRoot))
{
Directory.CreateDirectory(credentialRoot);
}
//暫存憑証用目錄
string tempPath = Path.Combine(credentialRoot, authorizationCode.State);
IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(
new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = GoogleClientSecrets.Load(stream).Secrets,
Scopes = scopes,
DataStore = new FileDataStore(tempPath)
});
//這個動作應該是要把 code 換成 token
await flow.ExchangeCodeForTokenAsync(Username, authorizationCode.Code, RedirectUri, CancellationToken.None).ConfigureAwait(false);
if (!string.IsNullOrWhiteSpace(authorizationCode.State))
{
string newPath = Path.Combine(credentialRoot, Username);
if (tempPath.ToLower() != newPath.ToLower())
{
if (Directory.Exists(newPath))
Directory.Delete(newPath, true);
Directory.Move(tempPath, newPath);
}
}
return "OK";
}
}
public async Task<bool> SendTestMail()
{
var service = await GetGmailService();
GmailMessage message = new GmailMessage();
message.Subject = "標題";
message.Body = $"<h1>內容</h1>";
message.FromAddress = "bikehsu@gmail.com";
message.IsHtml = true;
message.ToRecipients = "bikehsu@gmail.com";
message.Attachments = new List<Attachment>();
string filePath = @"C:\Users\bike\Pictures\Vegetable_pumpkin.jpg"; //要附加的檔案
Attachment attachment1 = new Attachment(filePath);
message.Attachments.Add(attachment1);
SendEmail(message, service);
Console.WriteLine("OK");
return true;
}
async Task<GmailService> GetGmailService()
{
UserCredential credential = null;
var credentialRoot = Path.Combine(SecretPath, "Credentials");
if (!Directory.Exists(credentialRoot))
{
Directory.CreateDirectory(credentialRoot);
}
string filePath = Path.Combine(credentialRoot, Username);
using (var stream = new FileStream(Path.Combine(SecretPath, "client_secret.json"), FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
Username,
CancellationToken.None,
new FileDataStore(filePath));
}
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Send Mail",
});
return service;
}
public class GmailMessage
{
public string FromAddress { get; set; }
public string ToRecipients { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
public bool IsHtml { get; set; }
public List<System.Net.Mail.Attachment> Attachments { get; set; }
}
public static void SendEmail(GmailMessage email, GmailService service)
{
var mailMessage = new System.Net.Mail.MailMessage();
mailMessage.From = new System.Net.Mail.MailAddress(email.FromAddress);
mailMessage.To.Add(email.ToRecipients);
mailMessage.ReplyToList.Add(email.FromAddress);
mailMessage.Subject = email.Subject;
mailMessage.Body = email.Body;
mailMessage.IsBodyHtml = email.IsHtml;
if (email.Attachments != null)
{
foreach (System.Net.Mail.Attachment attachment in email.Attachments)
{
mailMessage.Attachments.Add(attachment);
}
}
var mimeMessage = MimeKit.MimeMessage.CreateFromMailMessage(mailMessage);
var gmailMessage = new Google.Apis.Gmail.v1.Data.Message
{
Raw = Encode(mimeMessage)
};
Google.Apis.Gmail.v1.UsersResource.MessagesResource.SendRequest request = service.Users.Messages.Send(gmailMessage, "me");
request.Execute();
}
public static string Encode(MimeMessage mimeMessage)
{
using (MemoryStream ms = new MemoryStream())
{
mimeMessage.WriteTo(ms);
return Convert.ToBase64String(ms.GetBuffer())
.TrimEnd('=')
.Replace('+', '-')
.Replace('/', '_');
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: "Cors(PolicyName",
builder =>
{
builder.WithOrigins("https://web1.yourdomain.com",
"https://web2.yourdomain.com")
.AllowCredentials();
});
});
services.AddControllers()
.AddNewtonsoftJson(opt =>
opt.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver());
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseExceptionMiddleware();
app.UseHttpsRedirection();
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthorization();
$.ajax({
url: apiRoot + "apiurl",
type: 'GET',
dataType: 'json', // 預期從server接收的資料型態
success: function (res) {
console.log("success: ");
console.log(res);
},
xhrFields: {
withCredentials: true
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("發生錯誤");
}
});
<system.webServer>
...
<security>
<requestFiltering>
<!--1073741824 ==> 1GB-->
<requestLimits maxAllowedContentLength="1073741824" />
</requestFiltering>
</security>
...
</system.webServer>