PageRenderTime 58ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/AppLib/CE.Insights/Controllers/Version1/FileController.cs

https://bitbucket.org/jeffmccommas/acex
C# | 326 lines | 245 code | 26 blank | 55 comment | 19 complexity | 680769b5361b77a77b586fcb9c511aef MD5 | raw file
  1. using System;
  2. using System.Net;
  3. using System.Net.Http;
  4. using System.Web.Http;
  5. using System.Web.Http.Description;
  6. using CE.Infrastructure;
  7. using CE.Insights.Common.Filters;
  8. using CE.Insights.Models;
  9. using CE.Models;
  10. using CE.Models.Insights;
  11. using System.Threading.Tasks;
  12. using System.Net.Http.Headers;
  13. using System.IO;
  14. using CE.Models.Insights.Types;
  15. namespace CE.Insights.Controllers.Version1
  16. {
  17. /// <summary>
  18. /// The file endpoint stores files such as PDF reports on a server and enables the user to retrieve, update and delete them.
  19. /// </summary>
  20. [RequireHttpsAndClientCertAttribute]
  21. public class FileController : ApiController
  22. {
  23. private ClientUser _clientUser;
  24. private static IInsightsEFRepository _insightsEfRepository;
  25. public ClientUser MyClientUser
  26. {
  27. get { return _clientUser ?? (_clientUser = GetClientUser()); }
  28. set { _clientUser = value; }
  29. }
  30. public FileController() {
  31. _insightsEfRepository = new InsightsEfRepository();
  32. }
  33. /// <summary>
  34. /// Testability, passed in repository so not relying on data access through sql server
  35. /// </summary>
  36. /// <param name="insightsEfRepository"></param>
  37. public FileController(IInsightsEFRepository insightsEfRepository)
  38. {
  39. if (insightsEfRepository == null)
  40. {
  41. throw new ArgumentNullException("", @"InsightsRepository is null!");
  42. }
  43. _insightsEfRepository = insightsEfRepository;
  44. }
  45. /// <summary>
  46. /// GET Action request with the parameters in an encoded string.
  47. /// </summary>
  48. /// <param name="enc"></param>
  49. /// <returns></returns>
  50. public HttpResponseMessage Get([FromUri] string enc)
  51. {
  52. int fileId = 0;
  53. string customerId = null;
  54. string accountId = null;
  55. string premiseId = null;
  56. byte userRoleId = 0;
  57. string userId = null;
  58. bool getFiles = true;
  59. foreach (var aa in ActionContext.ActionArguments)
  60. {
  61. switch (aa.Key.ToLower())
  62. {
  63. case "customerid":
  64. customerId = aa.Value.ToString();
  65. break;
  66. case "accountid":
  67. accountId = aa.Value.ToString();
  68. break;
  69. case "premiseid":
  70. premiseId = aa.Value.ToString();
  71. break;
  72. case "userid":
  73. userId = aa.Value.ToString();
  74. break;
  75. case "roleid":
  76. userRoleId = byte.Parse(aa.Value.ToString());
  77. break;
  78. case "fileid":
  79. getFiles = false;
  80. fileId = int.Parse(aa.Value.ToString());
  81. break;
  82. }
  83. }
  84. if (getFiles)
  85. {
  86. var request = new FilesRequest()
  87. {
  88. CustomerId = customerId,
  89. AccountId = accountId,
  90. PremiseId = premiseId,
  91. UserId = userId,
  92. UserRole = userRoleId,
  93. };
  94. // Validate model via model annotations. This must execute here, since our enc is special.
  95. bool success;
  96. var resultModelState = ValidateModels.Validate(request, out success);
  97. return !success ? Request.CreateErrorResponse(HttpStatusCode.BadRequest, resultModelState) : Get(request);
  98. }
  99. return Get(fileId);
  100. }
  101. /// <summary>
  102. /// GET File request with un-encoded parameters. Retieve the file from Azure storage
  103. /// Returns requested file
  104. /// </summary>
  105. /// <param name="fileId"></param>
  106. /// <returns>File Stream</returns>
  107. [ResponseType(typeof(FileResponse))]
  108. public HttpResponseMessage Get([FromUri] int fileId)
  109. {
  110. HttpResponseMessage response;
  111. try
  112. {
  113. var clientUser = (ClientUser) ActionContext.Request.Properties[CEConfiguration.CEClientUser];
  114. var model = new FileModel(_insightsEfRepository);
  115. var fileresponse = model.GetFile(fileId, clientUser.ClientID);
  116. if(fileresponse.File != null)
  117. {
  118. var file = fileresponse.File;
  119. response = new HttpResponseMessage(HttpStatusCode.OK);
  120. file.FileContent.Seek(0, SeekOrigin.Begin);
  121. response.Content = new StreamContent(file.FileContent);
  122. response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
  123. response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
  124. response.Content.Headers.ContentDisposition.FileName = file.Name;
  125. response.Content.Headers.ContentLength = file.FileContent.Length;
  126. }
  127. else
  128. {
  129. return Request.CreateErrorResponse(HttpStatusCode.OK, fileresponse.Message);
  130. }
  131. }
  132. catch (Exception ex)
  133. {
  134. return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message);
  135. }
  136. return response;
  137. }
  138. /// <summary>
  139. /// GET Files request with un-encoded parameters. Retieve the List of the all the files for a User, Customer, Account and Premise.
  140. /// </summary>
  141. /// <param name="request"></param>
  142. /// <returns>List of files Metadata</returns>
  143. [ResponseType(typeof(FilesResponse))]
  144. public HttpResponseMessage Get([FromUri] FilesRequest request)
  145. {
  146. FilesResponse response;
  147. try
  148. {
  149. var clientUser = (ClientUser)ActionContext.Request.Properties[CEConfiguration.CEClientUser];
  150. var model = new FileModel(_insightsEfRepository);
  151. response = model.GetFiles(request, clientUser.ClientID);
  152. }
  153. catch (Exception ex)
  154. {
  155. return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message);
  156. }
  157. return (Request.CreateResponse(HttpStatusCode.OK, response));
  158. }
  159. /// <summary>
  160. /// Delete File request with the parameters in an encoded string.
  161. /// Delete the file in storage based on file Id.
  162. /// </summary>
  163. /// <param name="enc"></param>
  164. /// <returns></returns>
  165. [ResponseType(typeof(FileResponse))]
  166. public HttpResponseMessage Delete([FromUri] string enc)
  167. {
  168. int fileId=0;
  169. foreach (var aa in ActionContext.ActionArguments)
  170. {
  171. switch (aa.Key.ToLower())
  172. {
  173. case "fileid":
  174. fileId = int.Parse(aa.Value.ToString());
  175. break;
  176. }
  177. }
  178. var request = new FileRequest
  179. {
  180. FileId = fileId
  181. };
  182. // Validate model via model annotations. This must execute here, since our enc is special.
  183. bool success;
  184. var resultModelState = ValidateModels.Validate(request, out success);
  185. return !success ? Request.CreateErrorResponse(HttpStatusCode.BadRequest, resultModelState) : Delete(request);
  186. }
  187. /// <summary>
  188. /// Delete File request with un-encoded parameters.
  189. /// Delete the file in storage based on file Id.
  190. /// </summary>
  191. /// <param name="request"></param>
  192. /// <returns></returns>
  193. [ResponseType(typeof(FileResponse))]
  194. public HttpResponseMessage Delete([FromUri] FileRequest request)
  195. {
  196. FileResponse response;
  197. try
  198. {
  199. var clientUser = MyClientUser;
  200. var model = new FileModel(_insightsEfRepository);
  201. response = model.DeleteFile(request, clientUser.ClientID);
  202. }
  203. catch (Exception ex)
  204. {
  205. return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message);
  206. }
  207. return Request.CreateResponse(HttpStatusCode.OK, response);
  208. }
  209. /// <summary>
  210. /// POST File stores a file on a server and stores a record of it along with metadata about the utility customer, the user and the file.
  211. /// Accepts Form data CustomerId, AccountId, PremiseId, UserId, RoleId, Title, Description,File,TypeId and SourceId
  212. /// </summary>
  213. /// <returns></returns>
  214. [HttpPost]
  215. public async Task<HttpResponseMessage> Post()
  216. {
  217. FilePostResponse response;
  218. var model = new FileModel(_insightsEfRepository);
  219. if (!Request.Content.IsMimeMultipartContent("form-data"))
  220. {
  221. Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
  222. }
  223. var provider = new MultipartMemoryStreamProvider();
  224. var clientUser = MyClientUser;
  225. await Request.Content.ReadAsMultipartAsync(provider);
  226. var filePostrequest = new FilePostRequest {Filedetail = new FileDetail()};
  227. Stream stream = null;
  228. foreach (var formContent in provider.Contents)
  229. {
  230. // Extract name from Content-Disposition header. We know from earlier that the header is present.
  231. ContentDispositionHeaderValue contentDisposition = formContent.Headers.ContentDisposition;
  232. string formFieldName = UnquoteToken(contentDisposition.Name) ?? string.Empty;
  233. if (formFieldName == "File")
  234. {
  235. var fileName = UnquoteToken(formContent.Headers.ContentDisposition.FileName);
  236. filePostrequest.Filedetail.Name = fileName;
  237. stream = await formContent.ReadAsStreamAsync();
  238. }
  239. else
  240. {
  241. // Read the contents as string data and add to form data
  242. var formFieldValue = await formContent.ReadAsStringAsync();
  243. model.SetFileUploadDetails(formFieldName, formFieldValue, filePostrequest.Filedetail);
  244. }
  245. }
  246. try
  247. {
  248. response = model.ValidateFileUpload(filePostrequest);
  249. string postresult = string.Empty;
  250. if (response.StatusType != StatusType.ParameterErrors)
  251. {
  252. var extension = filePostrequest.Filedetail.Name.Remove(0, filePostrequest.Filedetail.Name.LastIndexOf(".", StringComparison.Ordinal));
  253. if (stream != null)
  254. {
  255. response = _insightsEfRepository.PostFile(clientUser.ClientID, filePostrequest);
  256. filePostrequest.Filedetail.BlobName = filePostrequest.Filedetail.CustomerId + "_" + filePostrequest.Filedetail.Id + extension;
  257. postresult = model.SaveFile(filePostrequest, stream, clientUser.ClientID);
  258. }
  259. if (!postresult.Equals("Success"))
  260. {
  261. _insightsEfRepository.DeleteFile(filePostrequest.Filedetail.Id);
  262. return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, CEConfiguration.Error_PostFailed);
  263. //response.Message = postresult;
  264. //response.StatusType = StatusType.Undefined;
  265. }
  266. }
  267. }
  268. catch (Exception)
  269. {
  270. return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, CEConfiguration.Error_PostFailed);
  271. }
  272. return (Request.CreateResponse(HttpStatusCode.OK, response));
  273. }
  274. /// <summary>
  275. /// Remove bounding quotes on a token if present
  276. /// </summary>
  277. /// <param name="token">Token to unquote.</param>
  278. /// <returns>Unquoted token.</returns>
  279. private static string UnquoteToken(string token)
  280. {
  281. if (string.IsNullOrWhiteSpace(token))
  282. {
  283. return token;
  284. }
  285. if (token.StartsWith("\"", StringComparison.Ordinal) && token.EndsWith("\"", StringComparison.Ordinal) && token.Length > 1)
  286. {
  287. return token.Substring(1, token.Length - 2);
  288. }
  289. return token;
  290. }
  291. /// <summary>
  292. /// Returns Client User object.
  293. /// </summary>
  294. /// <returns></returns>
  295. private ClientUser GetClientUser()
  296. {
  297. return (ClientUser)ActionContext.Request.Properties[CEConfiguration.CEClientUser];
  298. }
  299. }
  300. }