且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

jQuery $ .ajax调用WCF服务返回400错误请求

更新时间:2022-04-15 22:27:22

调用本身似乎没有任何问题-您应该尝试

The call by itself doesn't seem to have any problems - you should try to enable tracing to see why WCF is considering the incoming request to be bad. I tried a similar code as the one you have (see below) and it worked just fine. Also, since the request is coming from the same domain (localhost:16062) as the service, you don't have any cross-domain problems.

更新:基于问题评论线程的解决方案

< service>的名称"属性. web.config中的元素必须与服务类的标准名称(即名称空间+名称)相匹配(即,.svc文件中使用的值相同).否则,您将为您的服务添加一个默认端点,该端点可能不是您想要的-默认情况下,您将获得BasicHttpBinding端点,这不是您所需要的.

The "name" attribute of the <service> element in the web.config must match the fully-qualified name (i.e., the namespace + the name) of the service class (i.e., the same value used in the .svc file). Otherwise you'll get a default endpoint added for your service which may or may not be what you want - by default you get a BasicHttpBinding endpoint, which is not what you wanted in your case.

此问题是.NET Framework 4.0中添加的功能的不幸副作用:简化的配置.在.NET 3.5之前,每个服务都需要在web.config上有一个条目来对其进行配置,并且即使是最简单的应用程序(即hello world)的配置文件也很大.因此发生的事情是,从4.0开始,如果WCF找不到名称与该服务的标准名称匹配的服务元素,它将很高兴地认为您要使用默认配置.这就是为什么它刚开始与WcfTestClient一起工作的原因.

This problem is un unfortunate side effect of a feature added in .NET Framework 4.0: Simplified Configuration. Until .NET 3.5, every service needed to have an entry on web.config to configure it, and the config files for even the simplest applications (i.e., hello world) were big. So what happened is that, since 4.0, if WCF doesn't find a service element with a name which matches the fully-qualified name of the service, it will happily think that you want to use the default configuration. That's why it happens to "work" with the WcfTestClient at first.

public class ***_6526659
{
    [ServiceContract]
    public interface IGeoDataService
    {
        [OperationContract]
        [WebInvoke(Method = "POST",
            BodyStyle = WebMessageBodyStyle.Wrapped,
            ResponseFormat = WebMessageFormat.Json)]
        List<BranchData> GetBranches();
    }

    public class Service : IGeoDataService
    {
        public List<BranchData> GetBranches()
        {
            return new List<BranchData>();
        }
    }

    // Use a data contract as illustrated in the sample below to add composite types to service operations.
    [DataContract]
    public class BranchData
    {
        [DataMember]
        public string BranchNumber { get; set; }

        [DataMember]
        public string BranchName { get; set; }

        [DataMember]
        public string StreetAddress { get; set; }

        [DataMember]
        public string City { get; set; }

        [DataMember]
        public string Zip { get; set; }

        [DataMember]
        public string State { get; set; }

        [DataMember]
        public string Phone { get; set; }

        [DataMember]
        public string County { get; set; }
    }

    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
        WebHttpBinding binding = new WebHttpBinding { CrossDomainScriptAccessEnabled = true };
        WebHttpBehavior behavior = new WebHttpBehavior();
        host.AddServiceEndpoint(typeof(IGeoDataService), binding, "").Behaviors.Add(behavior);
        host.Open();
        Console.WriteLine("Host opened");

        HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(baseAddress + "/GetBranches");
        req.Method = "POST";
        req.GetRequestStream().Close();
        HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
        Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
        foreach (var header in resp.Headers.AllKeys)
        {
            Console.WriteLine("{0}: {1}", header, resp.Headers[header]);
        }
        if (resp.ContentLength > 0)
        {
            Console.WriteLine(new StreamReader(resp.GetResponseStream()).ReadToEnd());
        }

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}