ExceptionMessage:“无法将多个参数("tenant"和"certificateFile")绑定到请求的内容 [英] ExceptionMessage: "Can't bind multiple parameters ('tenant' and 'certificateFile') to the request's content

查看:34
本文介绍了ExceptionMessage:“无法将多个参数("tenant"和"certificateFile")绑定到请求的内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从react调用webapi,但出现此错误

I am trying to call a webapi from react and I get this error

responseJson = {消息:发生错误.",ExceptionMessage:无法将多个参数("tenant"和"certificateFile")绑定到请求的内容.",ExceptionType:"System.InvalidOperationException",StackTrace:位于System.Web.Http.Controllers.HttpActionBindin…tpControllerDispatcher.d__1.MoveNext()}

responseJson = {Message: "An error has occurred.", ExceptionMessage: "Can't bind multiple parameters ('tenant' and 'certificateFile') to the request's content.", ExceptionType: "System.InvalidOperationException", StackTrace: " at System.Web.Http.Controllers.HttpActionBindin…tpControllerDispatcher.d__1.MoveNext()"}

我的反应代码是这样的:

my react code is like this:

    import React, { Component } from 'react';
    import { Row, Col } from 'antd';
    import PageHeader from '../../components/utility/pageHeader';
    import Box from '../../components/utility/box';
    import LayoutWrapper from '../../components/utility/layoutWrapper.js';
    import ContentHolder from '../../components/utility/contentHolder';
    import basicStyle from '../../settings/basicStyle';
    import IntlMessages from '../../components/utility/intlMessages';
    import { adalApiFetch } from '../../adalConfig';

    export default class extends Component {
      constructor(props) {
        super(props);
        this.state = {tenantid: '', tenanturl: '', tenantpassword: '' };
        this.handleChangeTenantUrl = this.handleChangeTenantUrl.bind(this);
        this.handleChangeTenantPassword = this.handleChangeTenantPassword.bind(this);
        this.handleChangeTenantId= this.handleChangeTenantId.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
      };


      handleChangeTenantUrl(event){
        this.setState({tenanturl: event.target.value});
      }

      handleChangeTenantPassword(event){
        this.setState({tenantpassword: event.target.value});
      }

      handleChangeTenantId(event){
        this.setState({tenantid: event.target.value});
      }

      handleSubmit(event){
        event.preventDefault();

        const formData = new FormData();
        formData.append("TenantId", this.state.tenantid);
        formData.append("TenanrUrl", this.state.tenanturl);
        formData.append("TenantPassword", this.state.tenantpassword);

        const options = {
          method: 'put',
          data: formData,
          config: {
            headers: {
              'Content-Type': 'multipart/form-data'
            }
          }
        };

        adalApiFetch(fetch, "/Tenant", options)
          .then(response => response.json())
          .then(responseJson => {
            if (!this.isCancelled) {
              this.setState({ data: responseJson });
            }
          })
          .catch(error => {
            console.error(error);
          });
      }


      upload(e){
          let data = new FormData();
          //Append files to form data
          let files = e.target.files;
          for (let i = 0; i < files.length; i++) {
            data.append('files', files[i], files[i].name);
          }      
      }

      render(){
        const { data } = this.state;
        const { rowStyle, colStyle, gutter } = basicStyle;

        return (
          <div>
            <LayoutWrapper>
            <PageHeader>{<IntlMessages id="pageTitles.TenantAdministration" />}</PageHeader>
            <Row style={rowStyle} gutter={gutter} justify="start">
              <Col md={12} sm={12} xs={24} style={colStyle}>
                <Box
                  title={<IntlMessages id="pageTitles.TenantAdministration" />}
                  subtitle={<IntlMessages id="pageTitles.TenantAdministration" />}
                >
                  <ContentHolder>
                  <form onSubmit={this.handleSubmit}>
                    <label>
                      TenantId:
                      <input type="text" value={this.state.tenantid} onChange={this.handleChangeTenantId} />
                    </label>
                    <label>
                      TenantUrl:
                      <input type="text" value={this.state.tenanturl} onChange={this.handleChangeTenantUrl} />
                    </label>
                    <label>
                      TenantPassword:
                      <input type="text" value={this.state.tenantpassword} onChange={this.handleChangeTenantPassword} />
                    </label>
                    <label>
                      Certificate:
                      <input onChange = { e => this.upload(e) } type = "file" id = "files" ref = { file => this.fileUpload } />
                    </label>             
                  <input type="submit" value="Submit" />
                  </form>
                  </ContentHolder>
                </Box>
              </Col>
            </Row>
          </LayoutWrapper>
          </div>
        );
      }
    }

My web api is this:


public class TenantController : ApiController
    {
        public async Task<List<Tenant>> GetTenants()
        {
            var tenantStore = CosmosStoreFactory.CreateForEntity<Tenant>();
            return await tenantStore.Query().Where(x => x.TenantId != null ).ToListAsync();

        }

        public async Task<IHttpActionResult> GetTenant(string tenantId)
        {
            var tenantStore = CosmosStoreFactory.CreateForEntity<Tenant>();
            var tenant = await tenantStore.Query().FirstOrDefaultAsync(x => x.TenantId == tenantId);
            if (tenant == null)
            {
                return NotFound();
            }
            return Ok(tenant);
        }

        public async Task<IHttpActionResult>  PutTenant([FromBody]Tenant tenant, HttpPostedFile certificateFile)
        {
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["AzureStorageKey"].ToString());
            // Create the blob client.
            CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

            // Retrieve reference to a previously created container.
            CloudBlobContainer container = blobClient.GetContainerReference(ConfigurationManager.AppSettings["certificatesContainer"].ToString());

            // Retrieve reference to a blob named "myblob".
            CloudBlockBlob blockBlob = container.GetBlockBlobReference("myblob");

            // Create or overwrite the "myblob" blob with contents from a local file.
            blockBlob.Properties.ContentType = certificateFile.ContentType;
            blockBlob.UploadFromStream(certificateFile.InputStream);

            var tenantStore = CosmosStoreFactory.CreateForEntity<Tenant>();
            tenant.CertificatePath = blockBlob.Uri;

            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            //if (id != tenant.TenantId)
            //{
            //    return BadRequest();
            //}

            var added = await tenantStore.AddAsync(tenant);
            return StatusCode(HttpStatusCode.NoContent); 
        }

        public async Task<IHttpActionResult> PostTenant(string id, Tenant tenant)
        {
            var tenantStore = CosmosStoreFactory.CreateForEntity<Tenant>();

            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var result = await tenantStore.UpdateAsync(tenant);
            return Ok(result);
        }

        public async Task<IHttpActionResult> DeleteTenant(string tenantId)
        {
            var tenantStore = CosmosStoreFactory.CreateForEntity<Tenant>();
            await tenantStore.RemoveByIdAsync(tenantId);// Removes an entity with the specified ID
            return Ok(tenantId);
        }
    }

我的租户对象是这样:

public class Tenant
    {
        public string TenantId { get; set; }
        public string TenantUrl { get; set; }
        public Uri CertificatePath { get; set; }
        public string CertificatePassword { get; set; }

        public override string ToString()
        {
            return JsonConvert.SerializeObject(this);
        }
    }

和控制器

public class TenantController : ApiController
    {
        public async Task<List<Tenant>> GetTenants()
        {
            var tenantStore = CosmosStoreFactory.CreateForEntity<Tenant>();
            return await tenantStore.Query().Where(x => x.TenantId != null ).ToListAsync();

        }

        public async Task<IHttpActionResult> GetTenant(string tenantId)
        {
            var tenantStore = CosmosStoreFactory.CreateForEntity<Tenant>();
            var tenant = await tenantStore.Query().FirstOrDefaultAsync(x => x.TenantId == tenantId);
            if (tenant == null)
            {
                return NotFound();
            }
            return Ok(tenant);
        }

        public async Task<IHttpActionResult>  PutTenant([FromBody]Tenant tenant, HttpPostedFile certificateFile)
        {
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["AzureStorageKey"].ToString());
            // Create the blob client.
            CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

            // Retrieve reference to a previously created container.
            CloudBlobContainer container = blobClient.GetContainerReference(ConfigurationManager.AppSettings["certificatesContainer"].ToString());

            // Retrieve reference to a blob named "myblob".
            CloudBlockBlob blockBlob = container.GetBlockBlobReference("myblob");

            // Create or overwrite the "myblob" blob with contents from a local file.
            blockBlob.Properties.ContentType = certificateFile.ContentType;
            blockBlob.UploadFromStream(certificateFile.InputStream);

            var tenantStore = CosmosStoreFactory.CreateForEntity<Tenant>();
            tenant.CertificatePath = blockBlob.Uri;

            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            //if (id != tenant.TenantId)
            //{
            //    return BadRequest();
            //}

            var added = await tenantStore.AddAsync(tenant);
            return StatusCode(HttpStatusCode.NoContent); 
        }

        public async Task<IHttpActionResult> PostTenant(string id, Tenant tenant)
        {
            var tenantStore = CosmosStoreFactory.CreateForEntity<Tenant>();

            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var result = await tenantStore.UpdateAsync(tenant);
            return Ok(result);
        }

        public async Task<IHttpActionResult> DeleteTenant(string tenantId)
        {
            var tenantStore = CosmosStoreFactory.CreateForEntity<Tenant>();
            await tenantStore.RemoveByIdAsync(tenantId);// Removes an entity with the specified ID
            return Ok(tenantId);
        }
    }

推荐答案

问题恰好是异常消息中指定的问题.您将多个参数绑定到动作主体,而Web API无法做到这一点.请阅读 Web API中的参数绑定.

Problem is exactly what is specified in the exception message. You are binding multiple parameters to action body, you cannot do that with Web API. Please read Parameter binding in Web API.

使用以下代码读取上传的文件.

Use following code to read uploaded file.

    using System.Net.Http;
    using System.IO;
    public async Task<IHttpActionResult>  PutTenant([FromBody]Tenant tenant)
    {
            var provider = new MultipartMemoryStreamProvider();
            var contentType = "";
            Stream content = new MemoryStream();
            await base.Request.Content.ReadAsMultipartAsync(provider);
            if(provider.Contents.Count > 0)
            {
                contentType = provider.Contents[0].Headers.ContentType.MediaType;
                content = await provider.Contents[0].ReadAsStreamAsync();
            }

        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["AzureStorageKey"].ToString());
        // Create the blob client.
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

        // Retrieve reference to a previously created container.
        CloudBlobContainer container = blobClient.GetContainerReference(ConfigurationManager.AppSettings["certificatesContainer"].ToString());

        // Retrieve reference to a blob named "myblob".
        CloudBlockBlob blockBlob = container.GetBlockBlobReference("myblob");

        // Create or overwrite the "myblob" blob with contents from a local file.
        blockBlob.Properties.ContentType = contentType;
        blockBlob.UploadFromStream(content);

        var tenantStore = CosmosStoreFactory.CreateForEntity<Tenant>();
        tenant.CertificatePath = blockBlob.Uri;

        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        //if (id != tenant.TenantId)
        //{
        //    return BadRequest();
        //}

        var added = await tenantStore.AddAsync(tenant);
        return StatusCode(HttpStatusCode.NoContent); 
    }

这篇关于ExceptionMessage:“无法将多个参数("tenant"和"certificateFile")绑定到请求的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆