简体   繁体   English

为什么在Asp.Net控制器中没有为IFormFile进行模型绑定?

[英]Why is model-binding not occurring for IFormFile in my Asp.Net controller?

I've written some code (MetadataProcessor) that locates an xml file and sends it to an API ( http://localhost:5000/api/Events/UploadAzureEncodedMetadata ) to be parsed. 我已经编写了一些代码(MetadataProcessor),该代码查找xml文件并将其发送到要解析的API( http:// localhost:5000 / api / Events / UploadAzureEncodedMetadata )。 However, when the API is called, the IFormFile parameter is always null. 但是,在调用API时,IFormFile参数始终为null。 I've examined the resulting http request with fiddler to determine what is causing the model-binding problem (if that's what it is), but I see nothing wrong. 我已经用提琴手检查了产生的http请求,以确定是什么引起了模型绑定问题(如果那是事实),但是我没有发现任何错误。

Metadata processor: 元数据处理器:

 // Build a path to the directory containing the metadata file
            string folderName = string.Format("OUTPUT_ENCODER_{0}_{1}", eventId, id);
            string folderPath = Path.Combine(
                this._config.MediaBasePath,
                clientId.ToString(),
                eventId.ToString(),
                "results",
                folderName);

            // Find the metadata file
            string fileName = null;
            byte[] data = null;
            bool exists = false;
            string[] files = Directory.GetFiles(folderPath);

            foreach (var file in files)
            {
                if (file.EndsWith("_metadata.xml"))
                {
                    data = File.ReadAllBytes(file);
                    exists = true;
                    fileName = file;
                    break;
                }
            }

            // Generate token for access to Events controller
            TokenProvider tokens = new TokenProvider(this._config, this._logger);
            var authValue = new AuthenticationHeaderValue("Bearer", tokens.GetTokenObject(clientId));


            // Build the HttpClient
            HttpClient client = new HttpClient()
            {
                DefaultRequestHeaders =
                                            {
                                                Authorization = authValue
                                            }
            };

            // Bundle the xml data into the request body
            ByteArrayContent formFile = new ByteArrayContent(data, 0, data.Length);

            MultipartFormDataContent multiContent = new MultipartFormDataContent();
            multiContent.Add(formFile, "formFile", fileName);

            // Post to EventsController
            var baseUri = new Uri(this._config.BaseUrl);

            var url = new Uri(baseUri, string.Format("{0}api/Events/UploadAzureEncodedMetadata/{1}", baseUri, videoId));
            var result = await client.PostAsync(url.ToString(), multiContent);

The MVC controller in the API: API中的MVC控制器:

[HttpPost("UploadAzureEncodedMetadata/{id}")]
        [ProducesResponseType(201)]
        [ProducesResponseType(400)]
        [ProducesResponseType(401)]
        [ProducesResponseType(404)]
        public async Task<IActionResult> UpdateDuration([FromRoute]Guid id, [FromForm]IFormFile formFile)
        {
            // Find the video to update
            var video = await this.context.Videos.Where(v => v.Id == id).SingleOrDefaultAsync();
            if(formFile == null)
            {
                return this.BadRequest();
            }

            // Ensure that the service account has authorization
            var eventId = video.EventId;
            if (!await this.securityProvider.HasEventEditAccessAsync(eventId))
            {
                return this.Unauthorized();
            }

            // Attempt to deserialize the xml 
            int videoDuration = 0;

            try
            {
                var serializer = new XmlSerializer(typeof(AssetFiles));

                Stream stream = formFile.OpenReadStream();

                var assetFiles = (AssetFiles)serializer.Deserialize(stream);

                // Find duration and convert to seconds
                string durationString = assetFiles.AssetFile.Duration;
                TimeSpan durationTimeSpan = XmlConvert.ToTimeSpan(durationString);
                videoDuration = (int)durationTimeSpan.TotalSeconds;
            }
            catch(Exception ex)
            {
                return this.BadRequest();
            }

            // Update the video entry
            video.Duration = videoDuration;
            await this.context.SaveChangesAsync();

            return this.NoContent();

        }

Lastly, here's a raw readout of the http request produced by the MetadataProcessor, that resulted in a null value for formFile in the controller: 最后,这是MetadataProcessor产生的http请求的原始读取,导致控制器中formFile的值为空:

POST http://localhost:5000/api/Events/UploadAzureEncodedMetadata/dc14829c-3d1b-4379-615b-08d5f8d07e16 HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1OWNiODg5YS01YjRjLTRlMzUtOWMyOS0zYWQ3MGU4NTJhYTgiLCJqdGkiOiI5OTU3MWIyMy0xYTQwLTQ0OTUtOTE2Zi03NDY5YjYwYzI1N2MiLCJpYXQiOjE1MzM4MzM4NzAsIkV2ZW50UmVnVXNlciI6ZmFsc2UspOgHjFVudElkIjoiMTdhMjc4NDYtOTc1My00OGEzLTRlYzEtMDhkNGUxMjgwZjVhIiwibmJmIjoxNTMzODMzODcwLCJleHAiOjE1MzM4MzM5MzAsImlzcyI6IjYzYmVmM2NkYTM1OTRmZjBhOTdiYWFiYWJjYTQzODhmIiwiYXVkIjoiSW5mZXJub0NvcmUifQ.rhIjYRUtFjHWrrgd9XnmW4kMXaZ5UFyr2ApNK1EBJRI
Content-Type: multipart/form-data; boundary="1b6c2d6e-53d6-414c-bb1b-681ff9c766f0"
Content-Length: 2951
Host: localhost:5000

--1b6c2d6e-53d6-414c-bb1b-681ff9c766f0
Content-Disposition: form-data; name=formFile; filename="C:\tmp\17a27846-9753-48a3-4ec1-08d4e1280f5a\213e65ee-fff9-4668-b123-7d0746bb4b05\results\OUTPUT_ENCODER_213e65ee-fff9-4668-b123-7d0746bb4b05_00000000-0000-0000-0000-000000000000\a35f0612-7a07-4bec-a9fd-a61d2a2f71bb_metadata.xml"; filename*=utf-8''C%3A%5Ctmp%5C17a27846-9753-48a3-4ec1-08d4e1280f5a%5C213e65ee-fff9-4668-b123-7d0746bb4b05%5Cresults%5COUTPUT_ENCODER_213e65ee-fff9-4668-b123-7d0746bb4b05_00000000-0000-0000-0000-000000000000%5Ca35f0612-7a07-4bec-a9fd-a61d2a2f71bb_metadata.xml

<?xml version="1.0" encoding="utf-8"?>
<AssetFiles xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/windowsazure/mediaservices/2014/07/mediaencoder/inputmetadata">
  <AssetFile Name="bcff8e9a-7cb7-4d09-abd2-f04a83df1be1.mp4" Size="383631" Duration="PT5.568S" NumberOfStreams="2" FormatNames="mov,mp4,m4a,3gp,3g2,mj2" FormatVerboseName="QuickTime / MOV" StartTime="PT0S" OverallBitRate="551">
    <VideoTracks>
      <VideoTrack Id="1" Codec="h264" CodecLongName="H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10" TimeBase="1/90000" NumberOfFrames="166" StartTime="PT0S" Duration="PT5.533S" FourCC="avc1" Profile="Constrained Baseline" Level="3.0" PixelFormat="yuv420p" Width="560" Height="320" DisplayAspectRatioNumerator="0" DisplayAspectRatioDenominator="1" SampleAspectRatioNumerator="0" SampleAspectRatioDenominator="1" FrameRate="30" Bitrate="465" HasBFrames="0">
        <Disposition Default="1" Dub="0" Original="0" Comment="0" Lyrics="0" Karaoke="0" Forced="0" HearingImpaired="0" VisualImpaired="0" CleanEffects="0" AttachedPic="0" />
        <Metadata key="creation_time" value="2010-03-20T21:29:11.000000Z" />
        <Metadata key="language" value="und" />
        <Metadata key="encoder" value="JVT/AVC Coding" />
      </VideoTrack>
    </VideoTracks>
    <AudioTracks>
      <AudioTrack Id="2" Codec="aac" CodecLongName="AAC (Advanced Audio Coding)" TimeBase="1/48000" NumberOfFrames="261" StartTime="PT0S" Duration="PT5.568S" SampleFormat="fltp" ChannelLayout="mono" Channels="1" SamplingRate="48000" Bitrate="83" BitsPerSample="0">
        <Disposition Default="1" Dub="0" Original="0" Comment="0" Lyrics="0" Karaoke="0" Forced="0" HearingImpaired="0" VisualImpaired="0" CleanEffects="0" AttachedPic="0" />
        <Metadata key="creation_time" value="2010-03-20T21:29:11.000000Z" />
        <Metadata key="language" value="eng" />
      </AudioTrack>
    </AudioTracks>
    <Metadata key="major_brand" value="mp42" />
    <Metadata key="minor_version" value="0" />
    <Metadata key="compatible_brands" value="mp42isomavc1" />
    <Metadata key="creation_time" value="2010-03-20T21:29:11.000000Z" />
    <Metadata key="encoder" value="HandBrake 0.9.4 2009112300" />
  </AssetFile>
</AssetFiles>
--1b6c2d6e-53d6-414c-bb1b-681ff9c766f0--

I'm aware that there are other ways to upload xml data, but I'd prefer to keep the xml parsing on the api side of things, if possible. 我知道还有其他上传xml数据的方法,但我更愿意在可能的api方面保持xml解析。 Thanks! 谢谢!

Problem was solved when I removed the [FromRoute] attribute from the IFormFile parameter and the [ApiController] attribute (not shown in code) from the MVC controller. 当我从MVC控制器中删除IFormFile参数的[FromRoute]属性和[ApiController]属性(代码中未显示)时,问题已解决。 So as not to disrupt functionality on the controller, I'll be creating a new controller specifically for the UpdateDuration() action. 为了不破坏控制器上的功能,我将专门为UpdateDuration()操作创建一个新的控制器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM