ASP.NET MVC 4 WebApi 與 Extjs 的結合 -- 送出表單 ( Submit Form )
ASP.NET MVC 4 WebApi 與 Extjs 的結合 -- 動態複製表單並送出
ASP.NET MVC 4 WebApi 與 Extjs 的結合 -- 上傳檔案 ( FileUpload )
為了避免網路或其他因素造成只成功上傳某些資料,所以需要將Form跟File上傳到同一個WebApi做資料儲存
同時上傳資料與檔案,Controller無法自動區分Form跟File丟到指定的Model裡面,所以我們需要對傳上來的資料做處理。
每次傳上來的資料類別不同,做成共用的Method讓大部分的狀況都可以直接使用,而且自動轉成我們所指定的型別。
先把Request.Form傳進去,用Keys跑迴圈把Value放到Dictionary去,因為我們需要自動轉換型別,先把Dictionary轉成Json格式,然後讓JsonConvert.DeserializeObject<T>去幫我們做型別轉換的處理。
備註:Key跟欄位名稱要一樣,多的Key不會被放到Model,沒有資料的欄位會是null。
public T getSingleFormData<T>(NameValueCollection Form) { List<T> Data = new List<T>(); Dictionary<string, object> tmpData = new Dictionary<string, object>(); foreach (var item in Form.AllKeys) { tmpData.Add(item, Form[item]); } if (tmpData.Count > 0) { T formData = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(tmpData)); Data.Add(formData); } return Data.FirstOrDefault(); }
看完單筆資料接收,當然有可能資料是多筆,這邊需要做傳過來的Key做切割,然後判斷這是第幾筆資料,所以要對AllKeys做排序,避免傳過來的順序亂掉導致轉換後是錯誤的資料。
public List<T> getMultiFormData<T>(NameValueCollection Form) { List<T> Datas = new List<T>(); Dictionary<string, object> tmpData = new Dictionary<string, object>(); string Seq = string.Empty; foreach (var item in Form.AllKeys.OrderBy(x => x)) { string[] formName = item.Split('.'); string formSeq = formName[0].Substring(1, formName[0].Length - 2); if (string.IsNullOrEmpty(Seq) == false && Seq != formSeq) { if (tmpData.Count > 0) { T formData = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(tmpData)); Datas.Add(formData); } tmpData.Clear(); } Seq = formSeq; tmpData.Add(formName[1], Form[item]); } if (tmpData.Count > 0) { T formData = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(tmpData)); Datas.Add(formData); } return Datas; }
接下來做檔案的接收,因為直接把檔案存到資料庫,所以用Stream去存放。
public IDictionary<string, object> getFileData(HttpFileCollection Files) { Dictionary<string, object> FilesStream = new Dictionary<string, object>(); foreach (var item in Files.AllKeys) { HttpPostedFile File = Files[item]; if (string.IsNullOrEmpty(File.FileName) == false) { Dictionary<string, object> tmpFile = new Dictionary<string, object>(); tmpFile.Add("FileName", File.FileName); tmpFile.Add("Stream", File.InputStream); FilesStream.Add(item, tmpFile); } } return FilesStream; }
Method都寫完,開始動手寫資料處理的部分。
public HttpResponseMessage Post() { var httpRequest = HttpContext.Current.Request; //多筆 List<Products> AllProducts = getMultiFormData<Products>(httpRequest.Form); /* Code */ //單筆 Products Products = getSingleFormData<Products>(httpRequest.Form); /* Code */ //檔案 IDictionary<string, object> Files = getFileData(httpRequest.Files); foreach (var item in Files) { Dictionary<string, object> tmpFile = (Dictionary<string, object>)item.Value; /* Code */ } return Request.CreateResponse(HttpStatusCode.OK); }
David Kuo:
為什麼要傳參數,而不在Method直接取Request?
答:
如果從Method直接取Request,這樣不夠彈性,變成其他NameValueCollection、HttpFileCollection的資料要取就會沒辦法使用,然後也有可能在建立共用物件時發生Request未初始化的問題。
參考:
ASP.NET MVC 4 Web Api 回傳HttpResponseMessage遇到 System.ArgumentNullException: Value cannot be null. Parameter name: request
沒有留言 :
張貼留言