0

I need to import a file, and also the Person model that I have shown below.

I am able to upload the file, However, I am not able to retrieve the Person model data in the importFileAndOtherInfo method that I have written.

Note: I am testing this web API via Postman. How can I upload a file, and also send Person Model data via Postman?

Person

int pId
string PName
School schoolAttended

My implementation:

[HttpPost]
public async Task<int> importFileAndOtherInfo(Person person)
{

    var stream = HttpContext.Current.Request.Files[0].InputStream

    // HOW TO RETRIEVE THE PERSON DATA HERE.

}
Divyang Desai
  • 7,483
  • 13
  • 50
  • 76
Illep
  • 16,375
  • 46
  • 171
  • 302
  • You can add files with postman last version here's the link https://stackoverflow.com/a/16022213/8265882 – Ivan-San Jun 05 '19 at 19:50

2 Answers2

0

What I understood from your question is, you want to pass model data and the file in stream at the same time; you can't send it directly, the way around is to send file with IFormFile and add create your own model binder as follows,

public class JsonWithFilesFormDataModelBinder: IModelBinder
{
    private readonly IOptions<MvcJsonOptions> _jsonOptions;
    private readonly FormFileModelBinder _formFileModelBinder;

    public JsonWithFilesFormDataModelBinder(IOptions<MvcJsonOptions> jsonOptions, ILoggerFactory loggerFactory)
    {
        _jsonOptions = jsonOptions;
        _formFileModelBinder = new FormFileModelBinder(loggerFactory);
    }

    public async Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
            throw new ArgumentNullException(nameof(bindingContext));

        // Retrieve the form part containing the JSON
        var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.FieldName);
        if (valueResult == ValueProviderResult.None)
        {
            // The JSON was not found
            var message = bindingContext.ModelMetadata.ModelBindingMessageProvider.MissingBindRequiredValueAccessor(bindingContext.FieldName);
            bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, message);
            return;
        }

        var rawValue = valueResult.FirstValue;

        // Deserialize the JSON
        var model = JsonConvert.DeserializeObject(rawValue, bindingContext.ModelType, _jsonOptions.Value.SerializerSettings);

        // Now, bind each of the IFormFile properties from the other form parts
        foreach (var property in bindingContext.ModelMetadata.Properties)
        {
            if (property.ModelType != typeof(IFormFile))
                continue;

            var fieldName = property.BinderModelName ?? property.PropertyName;
            var modelName = fieldName;
            var propertyModel = property.PropertyGetter(bindingContext.Model);
            ModelBindingResult propertyResult;
            using (bindingContext.EnterNestedScope(property, fieldName, modelName, propertyModel))
            {
                await _formFileModelBinder.BindModelAsync(bindingContext);
                propertyResult = bindingContext.Result;
            }

            if (propertyResult.IsModelSet)
            {
                // The IFormFile was successfully bound, assign it to the corresponding property of the model
                property.PropertySetter(model, propertyResult.Model);
            }
            else if (property.IsBindingRequired)
            {
                var message = property.ModelBindingMessageProvider.MissingBindRequiredValueAccessor(fieldName);
                bindingContext.ModelState.TryAddModelError(modelName, message);
            }
        }

        // Set the successfully constructed model as the result of the model binding
        bindingContext.Result = ModelBindingResult.Success(model);
    }
} 

Model

[ModelBinder(typeof(JsonWithFilesFormDataModelBinder), Name = "data")]
public class Person
{
   public int pId {get; set;}
   public string PName {get; set;}
   public School schoolAttended {get; set;}
   public IFormFile File { get; set; }
}

Postman request:

enter image description here

Divyang Desai
  • 7,483
  • 13
  • 50
  • 76
0

I am using the same in netcoreapp2.2. Works successfully.

Now when migrating from notecoreapp2.2 to netcoreapp3.1 I'm facing issues with private readonly IOptions<MvcJsonOptions> _jsonOptions;

As MvcJsonOptions is a breaking change from core 2.2 to 3.0.

Check this: Migration of netcoreapp2.2 to netcoreapp3.1 - convert MvcJsonOptions to core3.1 compatable

Romias
  • 13,783
  • 7
  • 56
  • 85
Madhavi G
  • 1
  • 2
  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 16 '21 at 09:34