예제 #1
0
        public async Task <ActionResult <DocumentDetails> > PostDocument([FromForm] AddDocumentRequest doc, IFormFile file, ApiVersion version)      // ApiVersion required for Routing
        {
            _logger.LogInformation("Begin Upload of File {Name}", file.FileName);

            var fileContent = await file.GetFileBytesAsync(HttpContext.RequestAborted);

            if (!_validator.IsValid(file.FileName, fileContent, out var message))
            {
                _logger.LogError("Posted File {Name} is not Valid: {Error}", file.FileName, message);
                return(BadRequest(message));
            }

            var details = new DocumentDetailsDto
            {
                Description  = doc.Description,
                FileName     = file.FileName,
                Owner        = doc.Owner,
                Title        = doc.Title,
                FileSize     = file.Length,
                DocumentType = _fileInfoProvider.GetDocumentType(file.FileName)
            };

            try
            {
                var result = await _repository.InsertAsync(details, fileContent, HttpContext.RequestAborted);

                if (result <= 0)
                {
                    _logger.LogError("Unable to upload Document {Name} ({Title}). A document with this title already exists.", details.FileName, details.Title);
                    return(Conflict("A document with this title already exists"));
                }

                _logger.LogInformation("Document {Name} was uploaded as {Id} ({Title})", details.FileName, result, details.Title);

                return(CreatedAtAction(nameof(Get), new { version = version.ToString(), id = result }, result));
            }
            catch (Exception e)
            {
                _logger.LogError(e, "An error has prevented upload of Document {Name}", details.FileName);
                return(StatusCode(StatusCodes.Status500InternalServerError));
            }
        }
예제 #2
0
        public Task <long> InsertAsync(DocumentDetailsDto details, byte[] dataBytes, CancellationToken token)
        {
            if (details is null)
            {
                throw new ArgumentNullException(nameof(details));
            }

            if (dataBytes is null)
            {
                throw new ArgumentNullException(nameof(dataBytes));
            }

            return(Impl());

            async Task <long> Impl()
            {
                await new SyncContextRemover();

                if (string.IsNullOrWhiteSpace(details.Description))
                {
                    details.Description = await GetFileDescription(details.DocumentType, dataBytes);
                }

                using var scope = new TransactionScope(TransactionScopeOption.RequiresNew, TransactionScopeAsyncFlowOption.Enabled);

                await using var conn = await CreateAndOpenConnection(token);

                const string insertDetailsQuery = @"
INSERT INTO [dbo].[Documents] ([FileName], [Title], [Description], [FileSize], [DocumentType], [Owner])
VALUES (@FileName, @Title, @Description, @FileSize, @DocumentType, @Owner);
SELECT SCOPE_IDENTITY() AS ID;
";

                var  insertDetailsDefinition = CreateCommand(insertDetailsQuery, details, token);
                long newId;

                try
                {
                    newId = await conn.ExecuteScalarAsync <long>(insertDetailsDefinition);
                }
                // catching UniqueConstraint Violation -- just for demo
                catch (SqlException s) when(s.Number == SqlErrorCodeUniqueViolation)
                {
                    newId = 0;
                }

                // should probably throw an exception
                if (newId <= 0)
                {
                    return(0);                    // rolls back scope
                }
                const string insertDataQuery = @"
INSERT INTO [dbo].[DocumentContent] ([DocumentId], [Content])
VALUES (@Id, @Content)
";

                var insertDataDefinition = CreateCommand(insertDataQuery, new { Id = newId, Content = dataBytes }, token);
                await conn.ExecuteAsync(insertDataDefinition);

                scope.Complete();

                return(newId);
            }
        }