【问题标题】:WebInvoke POST "Method not allowed" in WcfWcf 中的 WebInvoke POST“方法不允许”
【发布时间】:2013-09-06 06:25:03
【问题描述】:

我的 Rest wcf 服务如下...

[ServiceContract]
public interface IWinPhoneService
{

[OperationContract]
[WebInvoke(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "getkpimeasuredata", Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped)]
List<MeasureData> GetKpiMeasureData(DomainData data);


[OperationContract]
[WebGet(UriTemplate = "getdata/{value}", ResponseFormat = WebMessageFormat.Json)]
string GetData(string value);


// TODO: Add your service operations here
}

[DataContract]
public class DomainData
{
    [DataMember]
    public int? KPIId
    {
        get;
        set ;
    }

[DataMember]
public int? ScorecardId
{
    get;
    set;
}

[DataMember]
public short? CumulativeMonth
{
    get;
    set;
}

[DataMember]
public int? EngineeringOrgId
{
    get;
    set;
}

[DataMember]
public int? BusinessOrgId
{
    get;
    set;
}
[DataMember]
public int? DataValuetypeId
{
    get;
    set;
}

}

当我使用 Restsharp 使用此服务时,如下所示

string URL = "http://<servername>:8085/WinPhoneService.svc";

            RestClient client = new RestClient(URL);

            RestRequest request = new RestRequest("getkpimeasuredata",Method.POST);
            DomainData data = new DomainData();
            data.KPIId = 1006;
            data.ScorecardId = 3;
            data.EngineeringOrgId = 11;
            data.DataValuetypeId = 1;
            data.CumulativeMonth = 463;
            data.BusinessOrgId = 1;

            string json = Newtonsoft.Json.JsonConvert.SerializeObject(data);

            json = "{\"data\" : " + json + "}";

            request.AddParameter("application/json; charset=utf-8", json, ParameterType.RequestBody);
            request.RequestFormat = DataFormat.Json;
 client.ExecuteAsync(request, response =>
            {
                if (response.StatusCode == HttpStatusCode.OK)
                {



                }
                else
                {
                    //NOK
                }
            });

甚至尝试了如下的webget方法..

 RestClient client1 = new RestClient(URL);
            RestRequest request1 = new RestRequest(string.Format("getdata/{0}", 1), Method.GET);
            request1.RequestFormat = DataFormat.Json;

            var x = client1.ExecuteAsync(request1, response =>
                {
                    if (response.StatusCode == HttpStatusCode.OK)
                    {

                    }
                });

我能够将 response.StatusCode 设置为 NotFound,即使我检查了提琴手 服务根本没有命中,并且当我验证了服务 URL 时 在作曲家我得到错误为 "HTTP/1.1 405 方法不允许"

甚至当我尝试使用如下 Webclient 时

string URL = "http://<servername>:8085/WinPhoneService.svc";
            WebClient wclient = new WebClient();
            wclient.UseDefaultCredentials = true;
            wclient.Headers["Content-Type"] = "application/json";


            DomainData kpidata = new DomainData();
            data.KPIId = 1006;
            data.ScorecardId = 3;
            data.EngineeringOrgId = 11;
            data.DataValuetypeId = 1;
            data.CumulativeMonth = 463;
            data.BusinessOrgId = 1;

            string json = SerializeJson(kpidata);
            String str = wclient.UploadString(new Uri(URL ),"getkpimeasuredata",json);

即使在这里我得到“HTTP/1.1 405 Method Not Allowed”,但至少在这种情况下它如fiddler所示命中服务

PFB 相同的 webconfig...

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation>
      <assemblies>
        <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      </assemblies>
    </compilation>
    <!--<httpRuntime targetFramework="4.0" />-->
  </system.web>
  <system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding name="webCorpBinding">
          <!--<security mode="TransportCredentialOnly">
            <transport clientCredentialType="Windows"></transport>
          </security>-->
        </binding>
      </webHttpBinding>

    </bindings>
    <behaviors>

      <endpointBehaviors>
        <behavior name="RESTCorpBehavior">
          <webHttp/>
        </behavior>

      </endpointBehaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true"  />
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service name="WinPhoneService.WinPhoneService">
        <endpoint name="WinPhoneServiceeCorp" address="" binding="webHttpBinding" bindingConfiguration="webCorpBinding" behaviorConfiguration="RESTCorpBehavior"
         contract="WinPhoneService.IWinPhoneService" />
      </service>
    </services>
    <!--<protocolMapping>
      <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>-->
    <!--<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />-->
  </system.serviceModel>
  <!--<system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    --><!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      --><!--
    <directoryBrowse enabled="true" />
  </system.webServer>-->


  <connectionStrings>
    <add name="ScaasEntities" connectionString="metadata=res://*/Scaas.csdl|res://*/Scaas.ssdl|res://*/Scaas.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=<servername>;initial catalog=<catalog>;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
  </entityFramework>
</configuration>

请帮助我解决同样的问题..

我在win8手机应用中使用的功能是

public async void  LoadKpiData()
        {
                       string URL = "http://rr1biscdevsql01:8085/WinPhoneService.svc/getkpimeasuredata;
            WebClient wclient = new WebClient();
            wclient.UseDefaultCredentials = true;
            wclient.Headers["Content-Type"] = "application/json";

            DomainData kpidata = new DomainData();
            kpidata.KPIId = 1006;
            kpidata.ScorecardId = 3;
            kpidata.EngineeringOrgId = 11;
            kpidata.DataValuetypeId = 1;
            kpidata.CumulativeMonth = 463;
            kpidata.BusinessOrgId = 1;

            string json = SerializeJson(kpidata);
            wclient.UploadStringAsync(new Uri(URL), json);

            wclient.UploadStringCompleted += (s, e) =>
                {

                };

        }

当我检查 Restclient 调用的响应时,出现如下错误

 {"ErrorCode":"1001","ErrorMessage":"System.Data.EntityCommandExecutionException: The data reader is incompatible with the specified 'ScaasModel.GetKPIMeasureData_Result'. A member of the type, 'ParamName', does not have a corresponding column in the data reader with the same name.\u000d\u000a   at System.Data.Query.InternalTrees.ColumnMapFactory.GetColumnMapsForType(DbDataReader storeDataReader, EdmType edmType, Dictionary`2 renameList)\u000d\u000a   at System.Data.Query.InternalTrees.ColumnMapFactory.CreateColumnMapFromReaderAndType(DbDataReader storeDataReader, EdmType edmType, EntitySet entitySet, Dictionary`2 renameList)\u000d\u000a   at System.Data.Query.InternalTrees.ColumnMapFactory.CreateFunctionImportStructuralTypeColumnMap(DbDataReader storeDataReader, FunctionImportMapping mapping, EntitySet entitySet, StructuralType baseStructuralType)\u000d\u000a   at System.Data.EntityClient.EntityCommandDefinition.FunctionColumnMapGenerator.System.Data.EntityClient.EntityCommandDefinition.IColumnMapGenerator.CreateColumnMap(DbDataReader reader)\u000d\u000a   at System.Data.Objects.ObjectContext.CreateFunctionObjectResult[TElement](EntityCommand entityCommand, EntitySet entitySet, EdmType edmType, MergeOption mergeOption)\u000d\u000a   at System.Data.Objects.ObjectContext.ExecuteFunction[TElement](String functionName, MergeOption mergeOption, ObjectParameter[] parameters)\u000d\u000a   at System.Data.Objects.ObjectContext.ExecuteFunction[TElement](String functionName, ObjectParameter[] parameters)\u000d\u000a   at ScaasWinPhone.Model.ScaasEntities.GetKPIMeasureData(Nullable`1 kPIID, Nullable`1 scorecardID, Nullable`1 cumulativeMonthCount, Nullable`1 engineeringOrgID, Nullable`1 businessOrgID, Nullable`1 dataValueTypeID, Nullable`1 debug, ObjectParameter errorText)\u000d\u000a   at ScaasWinphoneRepository.ScaasRepository.GetKpiMeasureData(Nullable`1 kpiId, Nullable`1 scorecardId, Nullable`1 cumulativeMonth, Nullable`1 engineeringOrgId, Nullable`1 businessOrgId, Nullable`1 dataValuetypeId)\u000d\u000a   at SCaaSWinPhoneService.SCaaSWinPhoneService.GetKpiMeasureData(KpiDomainData kpidata)"}

拉杰什 当我添加 [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] 在服务中和

<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

在 webconfig 中出现错误,因为服务无法激活,因为它不支持 ASP.NET 兼容性。为此应用程序启用了 ASP.NET 兼容性。在 web.config 中关闭 ASP.NET 兼容模式,或将 AspNetCompatibilityRequirements 属性添加到服务类型,并将 RequirementsMode 设置为“允许”或“必需”。

实际上,当我在 localhost 中运行服务时它工作正常,但是当我托管服务时它抛出错误..请帮助....

【问题讨论】:

  • 您能否先尝试通过从浏览器访问 GET 资源并获取响应来查看是否可以访问 REST 服务。确保在 Fiddler 中捕获请求,并请发布您的 Fiddler 原始请求
  • 是的,当在浏览器 http://:8085/WinPhoneService.svc/getdata/1 中调用时,我得到的 json 结果为“您输入:1”
  • 当我为 URL 提供“http://:8085/WinPhoneService.svc/getkpimeasuredata”而不是在 Uploadstring 中提及方法名称时...如果我使用 webclient 但如果我使用 Restclient 它根本不工作。请帮助
  • 如果您尝试通过浏览器访问 getkipmeasuredata,您应该遇到一些异常,因为您的方法配置为 POST 而不是 GET。您能否尝试使用 Fiddler 捕获原始请求并将其发布给我们以查看 POST 请求。
  • 我没有通过浏览器从代码本身访问getkipmeasuredata我正在尝试......正如我在提琴手中所说,当我使用Restclient时我没有收到任何服务调用......当我使用webclient和修改后的URL参数为 http://:8085/WinPhoneService.svc/getkpimeasuredata 而不是在uploadstring中传递方法名称一切正常......但我需要Restclient中的解决方案。请帮助

标签: wcf c#-4.0 webclient wcf-rest restsharp


【解决方案1】:
[WebInvoke(... , Method = "POST" ... )]List<MeasureData> GetKpiMeasureData(DomainData data);

上面的代码你使用了 POST 方法,但是你必须使用 GET 方法,因为 POST 方法只用于添加数据。

Http 动词是 POST 、 GET 、 Delete 和 PUT(Update) 。你必须先学习。

I used Get method and RestSharp.dll for my project 如果您想将我的项目用于 POST 方法,您可以使用以下代码

客户端

 var client1 = new RestClient("http://localhost:61111/Service1.svc");
            var request1 = new RestRequest("/AddPerson", Method.POST);
            Person person1 = new Person();
            person1.PersonID = 2;
            person1.Name = "Robert";
            person1.SurName = "Dan";
            JsonSerializer serial = new JsonSerializer();

            string temp = serial.Serialize(person1);
            Console.WriteLine(temp);
            Person tempPerson1 = new JavaScriptSerializer().Deserialize<Person>(temp);
            Console.WriteLine(tempPerson1.PersonID + " " + tempPerson1.Name + " " + tempPerson1.SurName);

服务器端

public class Service1 : IService1
{       
    private Person person = new Person() { PersonID = 1, Name = "John", SurName = "Albert" };
    public Person GetPerson()
    {
        return person;
    }
    public Person AddPerson(Person person)
    {
        return person;
    }
}


[ServiceContract]
public interface IService1
{

    [OperationContract]
    [WebInvoke(Method="GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/GetPerson")]
    Person GetPerson();
    [OperationContract]
    [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/AddPerson")]
    Person AddPerson(Person person);
}

【讨论】:

    【解决方案2】:

    看看这段代码

    我的服务器代码如下

    [ServiceContract]
        public interface IWinPhoneService
        {
            [OperationContract]
            [WebInvoke(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "getkpimeasuredata")]
            List<String> GetKpiMeasureData(DomainData data);
        }
    
    [DataContract]
        public class DomainData
    {
        [DataMember]
        public int? KPIId { get; set; }
    
        [DataMember]
        public int? ScorecardId { get; set; }
    
        [DataMember]
        public short? CumulativeMonth { get; set; }
    
        [DataMember]
        public int? EngineeringOrgId { get; set; }
    
        [DataMember]
        public int? BusinessOrgId { get; set; }
    
        [DataMember]
        public int? DataValuetypeId { get; set; }
    }
    

    现在我的接口实现如下

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
        [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
        public class WinPhoneService : IWinPhoneService
        {
            public List<string> GetKpiMeasureData(DomainData data)
            {
                if (data != null)
                {
                    return new List<string>()  {"Sample 1","Sample 2"};
                }
                return new List<string>() {"No data recieved"};
            }
        }
    

    用于端点元素配置的服务器端 web.config

    <system.serviceModel>
    <services>
        <service name="WinPhoneService.WinPhoneService">
                <endpoint address="" binding="webHttpBinding" behaviorConfiguration="web" bindingConfiguration="defaultRestJsonp" contract="WinPhoneService.IWinPhoneService">
                </endpoint>
              </service>
        </services>
        <behaviors>
        <endpointBehaviors>
                <behavior name="web">
                  <webHttp />
                  <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
                </behavior>        
        </endpointBehaviors> 
        </behaviors>
        <bindings>   
        <webHttpBinding>
                <binding name="defaultRestJsonp" crossDomainScriptAccessEnabled="true">
                  <readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="64" maxNameTableCharCount="2147483647" />
                  <security mode="None" />
                </binding>
      </webHttpBinding>
      </bindings>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />     
     </system.serviceModel>  
    

    现在有了以上所有设置,使用 RestSharpClient 在下面找到我的客户端代码:

    private static string ToStringUsingDataContractJsonSer<T>(T requestBody)
            {
                var serializer = new DataContractJsonSerializer(typeof(T));
                var ms = new MemoryStream();
                serializer.WriteObject(ms, requestBody);
                ms.Position = 0;
                var reader = new StreamReader(ms);
                return reader.ReadToEnd();
            }
    
    private string UseRestSharpApproach(string serviceBaseUrl, string resourceUrl, Method method, object requestBody)
            {
                var client = new RestClient();
                client.BaseUrl = serviceBaseUrl;
                var request = new RestRequest(method) { DateFormat = DataFormat.Xml.ToString(), Resource = resourceUrl };
                request.AddParameter("application/json", requestBody, ParameterType.RequestBody);            
                var response = client.Execute(request);
    
                string responseString;
                if (response.StatusCode == HttpStatusCode.OK)
                {
                    responseString = HttpUtility.HtmlDecode(response.Content);
                }
                else
                {
                    responseString = response.StatusDescription + " --------------------" + HttpUtility.HtmlDecode(response.Content);
                }
                return responseString;
            }
    
    public void CallRESTService()
    {
           UseRestSharpApproach(serviceBaseUrl, resourceUrl, Method.POST, ToStringUsingDataContractJsonSer<DomainData>(objDomainData));
    }
    

    确保在客户端使用时的 DomainData 对象与在服务器上使用的名称空间相同,以便序列化和反序列化顺利进行。

    现在我来自 Fiddler 的原始请求如下所示:

    POST http://servername/Sample/WinPhoneService.svc/GetKpiMeasureData HTTP/1.1
    Accept: application/json, application/xml, text/json, text/x-json, text/javascript, text/xml
    User-Agent: RestSharp 102.0.0.0
    Content-Type: application/json
    Host: servername
    Content-Length: 112
    Accept-Encoding: gzip, deflate
    
    {"BusinessOrgId":1,"CumulativeMonth":463,"DataValuetypeId":1,"EngineeringOrgId":11,"KPIId":1006,"ScorecardId":3}
    

    响应如下:

    HTTP/1.1 200 OK
    Cache-Control: private
    Content-Length: 23
    Content-Type: application/json; charset=utf-8
    Server: Microsoft-IIS
    X-AspNet-Version: 4.0.30319
    Set-Cookie: ASP.NET_SessionId=123450p12rvdmnh3qrx2ocip; path=/; HttpOnly
    Date: Tue, 03 Sep 2013 10:11:51 GMT
    
    ["Sample 1","Sample 2"]
    

    【讨论】:

    • 感谢您的回复,您的 URI 模板是 getkpimeasuredata 但在您提到 GetKpiMeasureData 的 url 中,您能告诉我您如何传递 UseRestSharpApproach 函数的参数
    • 请看这篇可能有帮助的 SO 帖子:stackoverflow.com/questions/6312970/…
    • Rajesh 实际上我还需要从 windows phone 8 项目执行休息呼叫,它是一个移动应用程序..当我使用 webclient 休息呼叫正在从控制台应用程序工作但当我从移动设备运行相同的代码时应用程序即时获取 System.Net.WebException:远程服务器返回错误:NotFound。使用异步函数时出错,请参阅上面的更新代码
    • 您可以先尝试在同步中运行它们,看看是否有效。我不确定是否有来自 win phone 8 的模拟器供我提供样本。尝试在您的服务器上启用跟踪,然后检查跟踪文件以查看更详细的信息。当您的服务没有任何身份验证时,为什么要使用默认凭据。
    • 实际上问题出在 winphone 8 上,无法识别托管的 wcf url,但是当我将 servicebus 集成到 Webclient 时,它正在工作(如果我提供服务总线 url 而不是托管的 wcf url)与 Webclient 而不是 Restclient ,实际上我使用实体和我使用动态sql返回结果集的sp ..我在上面编辑的问题中提到的Restclient调用中出现错误。请帮助
    猜你喜欢
    • 2012-07-10
    • 2011-09-04
    • 1970-01-01
    • 2018-07-21
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 2011-10-01
    相关资源
    最近更新 更多