protected void ValidateModel <TFormFileModel>(TFormFileModel logUploadData) { foreach (var requiredFormFileProperty in FormFileAttributeHelper.GetRequiredFormFileProperties(typeof(TFormFileModel))) { var fileName = requiredFormFileProperty.GetValue(logUploadData); if (!TempFileService.Files.Contains(fileName)) { ModelState.AddModelError(requiredFormFileProperty.Name, $"File '{requiredFormFileProperty.Name}' with name: '{fileName}' not found in request."); } } }
protected async Task <KeyValueAccumulator> BuildMultiPartFormAccumulator <TModel>() where TModel : class, new() { var httpContextRequest = HttpContext.Request; // Used to accumulate all the form url encoded key value pairs in the request var formAccumulator = new KeyValueAccumulator(); var boundary = Request.GetBoundary(_defaultFormOptions); var reader = new MultipartReader(boundary, httpContextRequest.Body); Logger.LogDebug("Reading next section"); var section = await reader.ReadNextSectionAsync(); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { Logger.LogDebug("Content Disposition Header: {0}", section.ContentDisposition); if (contentDisposition.IsFileContentDisposition()) { var fileName = contentDisposition.FileName.Value; var formFileNames = FormFileAttributeHelper.GetFormFileNames(typeof(TModel)); if (!formFileNames.Contains(contentDisposition.Name.Value)) { Logger.LogWarning($"Unknown file '{contentDisposition.Name.Value}' with fileName: '{fileName}' is being ignored."); // Drains any remaining section body that has not been consumed and // reads the headers for the next section. section = await reader.ReadNextSectionAsync(); continue; } formAccumulator.Append(contentDisposition.Name.Value, fileName); var path = await TempFileService.CreateFromStreamAsync(fileName, section.Body); Logger.LogInformation($"Copied the uploaded file '{fileName}' to path: '{path}'"); } else if (contentDisposition.IsFormDataContentDisposition()) { // Content-Disposition: form-data; name="key" // Do not limit the key name length here because the // multipart headers length limit is already in effect. var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name); Logger.LogDebug("Retrieving value for {0}", key); var encoding = section.GetEncoding(); var streamReader = new StreamReader( section.Body, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true); using (streamReader) { // The value length limit is enforced by MultipartBodyLengthLimit var value = await streamReader.ReadToEndAsync(); if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase)) { value = string.Empty; } formAccumulator.Append(key.Value, value); if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit) { throw new InvalidDataException( $"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded."); } } } } // Drains any remaining section body that has not been consumed and // reads the headers for the next section. section = await reader.ReadNextSectionAsync(); } return(formAccumulator); }