#c# #asp.net #model-view-controller #razor
#c# #asp.net #model-view-controller #razor
Вопрос:
Я получаю эту действительно информативную ошибку. Но не могу найти проблему.
{"ClassName":"Newtonsoft.Json.JsonSerializationException","Message":"Could not create an instance of type Microsoft.AspNetCore.Http.IFormFile. Type is an interface or abstract class and cannot be instantiated. Path 'file.ContentDisposition', line 1, position 63.","Data":null,"InnerException":null,"HelpURL":null,"StackTraceString":" at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Booleanamp; createdFromNonDefaultCreator)rn at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)rn at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)rn at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)rn at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)rn at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)rn at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)rn at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)rn at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)rn at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)rn at Newtonsoft.Json.JsonSerializer.Deserialize[T](JsonReader reader)rn at Microsoft.Azure.Cosmos.CosmosJsonDotNetSerializer.FromStream[T](Stream stream)rn at Microsoft.Azure.Cosmos.CosmosJsonSerializerWrapper.FromStream[T](Stream stream)rn at Microsoft.Azure.Cosmos.CosmosSerializerCore.FromStream[T](Stream stream)rn at Microsoft.Azure.Cosmos.CosmosResponseFactoryCore.ToObjectpublic[T](ResponseMessage responseMessage)rn at Microsoft.Azure.Cosmos.CosmosResponseFactoryCore.<CreateItemResponse>b__8_0[T](ResponseMessage cosmosResponseMessage)rn at Microsoft.Azure.Cosmos.CosmosResponseFactoryCore.ProcessMessage[T](ResponseMessage responseMessage, Func`2 createResponse)rn at Microsoft.Azure.Cosmos.CosmosResponseFactoryCore.CreateItemResponse[T](ResponseMessage responseMessage)rn at Microsoft.Azure.Cosmos.ContainerCore.CreateItemAsync[T](CosmosDiagnosticsContext diagnosticsContext, T item, Nullable`1 partitionKey, ItemRequestOptions requestOptions, CancellationToken cancellationToken)rn at Microsoft.Azure.Cosmos.ClientContextCore.RunWithDiagnosticsHelperAsync[TResult](CosmosDiagnosticsContext diagnosticsContext, Func`2 task)rn at SmartLearning_salon.Services.Person.PersonService.AddItemAsync(Person person) in C:\Users\knoer\source\repos\SmartLearning_salon\SmartLearning_salon\Services\Person\PersonService.cs:line 25rn at SmartLearning_salon.Controllers.PersonController.Create(Person person) in C:\Users\knoer\source\repos\SmartLearning_salon\SmartLearning_salon\Controllers\PersonController.cs:line 67","RemoteStackTraceString":null,"RemoteStackIndex":0,"ExceptionMethod":null,"HResult":-2146233088,"Source":"Newtonsoft.Json","WatsonBuckets":null}
Контроллер в моем ASP.NET Приложение MVC сначала отправляет файл в хранилище Azure, а затем добавляет запись в Cosmos DB. И файл, и запись сохранены правильно. Но затем после сохранения страница возвращается со следующей ошибкой
«Не удалось создать экземпляр типа Microsoft.AspNetCore.Http.IFormFile»
Я знаю, что невозможно создать экземпляр объекта из интерфейса, но где это происходит?
В моем ASP.NET Ядро MVC 3.1 У меня есть модель, которая выглядит следующим образом
public class Person
{
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "ssn")]
public string Ssn { get; set; }
//[JsonProperty(PropertyName = "testresult")]
//public bool TestResult { get; set; }
[JsonProperty(PropertyName = "file")]
public IFormFile File { get; set; }
}
Мой PersonController выглядит следующим образом
// POST: PersonController/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(Person person)
{
using (var stream = new MemoryStream())
{
try
{
// assume a single file POST
await person.File.CopyToAsync(stream);
stream.Seek(0, SeekOrigin.Begin);
// now send blob up to Azure
await _blobStorageService.CreateBlobAsync(person.File.OpenReadStream(), person.File.FileName);
// send to Cosmos
await _personService.AddItemAsync(person);
//Ændre dette til at returnere et til detail view
return View("Person");
//return Ok(new { fileuploaded = true });
}
catch (Exception ex)
{
return BadRequest(ex);
}
}
}
Мой PersonService
public async Task AddItemAsync(Models.Person person)
{
await container.CreateItemAsync(person, new PartitionKey(person.Id));
}
My StorageService
public async Task CreateBlobAsync(Stream stream, string filename)
{
try
{
//Opret hvis ikkke eksisterer
await bcc.CreateIfNotExistsAsync();
await bcc.UploadBlobAsync(filename, stream);
}
catch (Exception)
{
throw;
}
}
Я действительно ценю всю помощь, которую я могу получить.
Спасибо, Клаус
Ответ №1:
IFormFile
это интерфейс. Они не могут быть созданы без контекста.
Вы пытаетесь использовать свою версию с кодировкой формы Person
для моделирования хранилища данных.
У вас должно быть две отдельные модели: одна для отправки формы, другая для хранения данных:
public class PersonForm
{
public string Id { get; set; }
public string Name { get; set; }
public string Ssn { get; set; }
public IFormFile File { get; set; }
}
public class Person
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("ssn")]
public string Ssn { get; set; }
[JsonProperty("fileName")]
public string FileName { get; set; }
}
Тогда ваша конечная точка будет выглядеть следующим образом:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([FromForm] PersonForm personForm)
{
try
{
// now send blob up to Azure
await _blobStorageService.CreateBlobAsync(
personForm.File.OpenReadStream(), personForm.File.FileName);
// send to Cosmos
await _personService.AddItemAsync(new Person
{
Id = personForm.Id,
Name = personForm.Name,
Ssn = personForm.Ssn,
FileName = personForm.File.FileName
});
//Ændre dette til at returnere et til detail view
return View("Person");
}
catch (Exception ex)
{
return BadRequest(ex);
}
}
Вы могли бы использовать AutoMapper
, чтобы значительно упростить копирование объектов DTO, когда многие свойства одинаковы.
Комментарии:
1. Большое спасибо за ваш отзыв. Следующий вопрос. Я также хотел бы сохранить данные IFormFile о сохраненном изображении в базе данных Cosmos. Возможно ли это?
2. @KN — нет. IFormFile предназначен исключительно для передачи файлов из интерфейса в серверную часть. Вы не можете сохранить их. Они живут в течение срока действия запроса, затем они исчезают. Но вы могли бы поместить ссылку на имя, которое оказалось в хранилище больших двоичных объектов. Обновил мой ответ.