在带有 Wcf 服务的 Angular JS 的预检响应中,Access-Control-Allow-Methods 不允许方法 PUT

Posted

技术标签:

【中文标题】在带有 Wcf 服务的 Angular JS 的预检响应中,Access-Control-Allow-Methods 不允许方法 PUT【英文标题】:Method PUT is not allowed by Access-Control-Allow-Methods in preflight response in Angular JS With Wcf Service 【发布时间】:2018-01-30 01:20:32 【问题描述】:

我正在开发 Wcf 服务。我在 Angular JS 应用程序中使用 Wcf 服务。我的 Post、Delete 和 Put 操作正在运行,但是当我尝试更新记录时出现以下错误...

XMLHttpRequest 无法加载 http://localhost:56766/StudentService.svc/UpdateStudent。方法 PUT 是 预检响应中的 Access-Control-Allow-Methods 不允许。

这是 Wcf 服务代码...

   [ServiceContract]
    public interface IStudentService
    

        [OperationContract]
        [WebInvoke(Method = "GET",
           RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json,
           UriTemplate = "/GetAllStudent/")]
        List<StudentDataContract> GetAllStudent();

        [OperationContract]
        [WebGet(RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json,
           UriTemplate = "/GetStudentDetails/StudentId")]
        StudentDataContract GetStudentDetails(string StudentId);

        [OperationContract]
        [WebInvoke(Method = "POST",
           RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json,
           UriTemplate = "/AddNewStudent")]
        bool AddNewStudent(StudentDataContract student);

        [OperationContract]
        [WebInvoke(Method = "PUT",
           RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json,
           UriTemplate = "/UpdateStudent")]
        void UpdateStudent(StudentDataContract contact);

        [OperationContract]
        [WebInvoke(Method = "DELETE",
           RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json,
           UriTemplate = "DeleteStudent/StudentId")]
        void DeleteStudent(string StudentId);

    


这里是实现

public class StudentService : IStudentService
    
        SchoolManagementEntities ctx;

        public StudentService()
        
            ctx = new SchoolManagementEntities();
        

        public List<StudentDataContract> GetAllStudent()
        
            //if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            //    return null;

            var query = (from a in ctx.Students
                         select a).Distinct();

            List<StudentDataContract> studentList = new List<StudentDataContract>();

            query.ToList().ForEach(rec =>
            
                studentList.Add(new StudentDataContract
                
                    StudentID = Convert.ToString(rec.StudentID),
                    Name = rec.Name,
                    Email = rec.Email,
                    EnrollYear = rec.EnrollYear,
                    Class = rec.Class,
                    City = rec.City,
                    Country = rec.Country
                );
            );
            return studentList;
        

        public StudentDataContract GetStudentDetails(string StudentId)
        
            //if (HttpContext.Current.Request.HttpMethod == "OPTIONS") ;

            StudentDataContract student = new StudentDataContract();

            try
            
                int Emp_ID = Convert.ToInt32(StudentId);
                var query = (from a in ctx.Students
                             where a.StudentID.Equals(Emp_ID)
                             select a).Distinct().FirstOrDefault();

                student.StudentID = Convert.ToString(query.StudentID);
                student.Name = query.Name;
                student.Email = query.Email;
                student.EnrollYear = query.EnrollYear;
                student.Class = query.Class;
                student.City = query.City;
                student.Country = query.Country;
            
            catch (Exception ex)
            
                throw new FaultException<string>
                        (ex.Message);
            
            return student;
        

        public bool AddNewStudent(StudentDataContract student)
        
            //if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            //    return true;
            try
            
                Student std = ctx.Students.Create();
                std.Name = student.Name;
                std.Email = student.Email;
                std.Class = student.Class;
                std.EnrollYear = student.EnrollYear;
                std.City = student.City;
                std.Country = student.Country;

                ctx.Students.Add(std);
                ctx.SaveChanges();
            
            catch (Exception ex)
            
                throw new FaultException<string>
                        (ex.Message);
            
            return true;
        

        public void UpdateStudent(StudentDataContract student)
        
            //if (HttpContext.Current.Request.HttpMethod == "OPTIONS")


            try
            
                int Stud_Id = Convert.ToInt32(student.StudentID);
                Student std = ctx.Students.Where(rec => rec.StudentID == Stud_Id).FirstOrDefault();
                std.Name = student.Name;
                std.Email = student.Email;
                std.Class = student.Class;
                std.EnrollYear = student.EnrollYear;
                std.City = student.City;
                std.Country = student.Country;

                ctx.SaveChanges();
            
            catch (Exception ex)
            
                throw new FaultException<string>
                        (ex.Message);
            
        

        public void DeleteStudent(string StudentId)
        
            //if (HttpContext.Current.Request.HttpMethod == "OPTIONS") 

            try
            
                int Stud_Id = Convert.ToInt32(StudentId);
                Student std = ctx.Students.Where(rec => rec.StudentID == Stud_Id).FirstOrDefault();
                ctx.Students.Remove(std);
                ctx.SaveChanges();
            
            catch (Exception ex)
            
                throw new FaultException<string>
                        (ex.Message);
            
        
    

这是 Gobal.aspx 的代码 ...

    public class Global : System.Web.HttpApplication
    

        protected void Application_Start(object sender, EventArgs e)
        

        

        protected void Session_Start(object sender, EventArgs e)
        

        

        protected void Application_BeginRequest(object sender, EventArgs e)
        
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
            if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "DELETE");

                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
                HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
                HttpContext.Current.Response.End();
            
        

        protected void Application_AuthenticateRequest(object sender, EventArgs e)
        

        

        protected void Application_Error(object sender, EventArgs e)
        

        

        protected void Session_End(object sender, EventArgs e)
        

        

        protected void Application_End(object sender, EventArgs e)
        

        
    

这里是 Angular JS 代码....

/// <reference path="../angular.min.js" />  
var app;

(function () 
    app = angular.module("RESTClientModule", []);

    app.controller("CRUD_AngularJs_RESTController", function ($scope, CRUD_AngularJs_RESTService) 

        $scope.OperType = 1;
        //1 Mean New Entry  

        GetAllRecords();
        //To Get All Records  
        function GetAllRecords() 
            var promiseGet = CRUD_AngularJs_RESTService.getAllStudent();
            promiseGet.then(function (pl)  $scope.Students = pl.data ,
                function (errorPl) 
                    $log.error('Some Error in Getting Records.', errorPl);
                );
        

        //To Clear all input controls.  
        function ClearModels() 
            $scope.OperType = 1;
            $scope.StudentID = "";
            $scope.Name = "";
            $scope.Email = "";
            $scope.Class = "";
            $scope.EnrollYear = "";
            $scope.City = "";
            $scope.Country = "";
        

        //To Create new record and Edit an existing Record.  
        $scope.save = function () 
            var Student = 
                Name: $scope.Name,
                Email: $scope.Email,
                Class: $scope.Class,
                EnrollYear: $scope.EnrollYear,
                City: $scope.City,
                Country: $scope.Country
            ;
            if ($scope.OperType === 1) 
                var promisePost = CRUD_AngularJs_RESTService.post(Student);
                promisePost.then(function (pl) 
                    $scope.StudentID = pl.data.StudentID;
                    GetAllRecords();

                    ClearModels();
                , function (err) 
                    console.log("Some error Occured" + err);
                );
             else 
                //Edit the record      
                debugger;
                Student.StudentID = $scope.StudentID;
                var promisePut = CRUD_AngularJs_RESTService.put($scope.StudentID, Student);
                promisePut.then(function (pl) 
                    $scope.Message = "Student Updated Successfuly";
                    GetAllRecords();
                    ClearModels();
                , function (err) 
                    console.log("Some Error Occured." + err);
                );
            
        ;

        //To Get Student Detail on the Base of Student ID  
        $scope.get = function (Student) 
            var promiseGetSingle = CRUD_AngularJs_RESTService.get(Student.StudentID);
            promiseGetSingle.then(function (pl) 
                var res = pl.data;
                $scope.StudentID = res.StudentID;
                $scope.Name = res.Name;
                $scope.Email = res.Email;
                $scope.Class = res.Class;
                $scope.EnrollYear = res.EnrollYear;
                $scope.City = res.City;
                $scope.Country = res.Country;
                $scope.OperType = 0;
            ,
                function (errorPl) 
                    console.log('Some Error in Getting Details', errorPl);
                );
        

        //To Delete Record  
        $scope.delete = function (Student) 
            var promiseDelete = CRUD_AngularJs_RESTService.delete(Student.StudentID);
            promiseDelete.then(function (pl) 
                $scope.Message = "Student Deleted Successfuly";
                GetAllRecords();
                ClearModels();
            , function (err) 
                console.log("Some Error Occured." + err);
            );
        
    );

    app.service("CRUD_AngularJs_RESTService", function ($http) 
        //Create new record  
        this.post = function (Student) 
            var request = $http(
                method: "post",
                url: "http://localhost:56766/StudentService.svc/AddNewStudent",
                data: Student
            );
            return request;
        

        //Update the Record  
        this.put = function (StudentID, Student) 
            debugger;
            var request = $http(
                method: "put",
                url: "http://localhost:56766/StudentService.svc/UpdateStudent",
                data: Student
            );
            return request;
        

        this.getAllStudent = function () 
            return $http.get("http://localhost:56766/StudentService.svc/GetAllStudent");
        ;

        //Get Single Records  
        this.get = function (StudentID) 
            return $http.get("http://localhost:56766/StudentService.svc/GetStudentDetails/" + StudentID);
        

        //Delete the Record  
        this.delete = function (StudentID) 
            var request = $http(
                method: "delete",
                url: "http://localhost:56766/StudentService.svc/DeleteStudent/" + StudentID
            );
            return request;
        

    );

)();

这是 html 代码 ...

@
    Layout = null;


<!DOCTYPE html>

<html data-ng-app="RESTClientModule">
<head title="ASAS">
    <title></title>
    <script src="~/Scripts/angular.min.js"></script>
    <script src="~/Scripts/MyScripts/Modules.js"></script>
</head>
<body>
    <table id="tblContainer" data-ng-controller="CRUD_AngularJs_RESTController">
        <tr>
            <td>
                <table style="border: solid 2px Green; padding: 5px;">
                    <tr style="height: 30px; background-color: skyblue; color: maroon;">
                        <th></th>
                        <th>ID</th>
                        <th>Name</th>
                        <th>Email</th>
                        <th>Class</th>
                        <th>Year</th>
                        <th>City</th>
                        <th>Country</th>
                        <th></th>
                        <th></th>
                    </tr>
                    <tbody data-ng-repeat="stud in Students">
                        <tr>
                            <td></td>
                            <td><span>stud.StudentID</span></td>
                            <td><span>stud.Name</span></td>
                            <td><span>stud.Email</span></td>
                            <td><span>stud.Class</span></td>
                            <td><span>stud.EnrollYear</span></td>
                            <td><span>stud.City</span></td>
                            <td><span>stud.Country</span></td>
                            <td>
                                <input type="button" id="Edit" value="Edit" data-ng-click="get(stud)" />
                            </td>
                            <td>
                                <input type="button" id="Delete" value="Delete" data-ng-click="delete(stud)" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </td>
        </tr>
        <tr>
            <td>
                <div style="color: red;">Message</div>
                <table style="border: solid 4px Red; padding: 2px;">
                    <tr>
                        <td></td>
                        <td>
                            <span>Student ID</span>
                        </td>
                        <td>
                            <input type="text" id="StudentID" readonly="readonly" data-ng-model="StudentID" />
                        </td>
                    </tr>
                    <tr>
                        <td></td>
                        <td>
                            <span>Student Name</span>
                        </td>
                        <td>
                            <input type="text" id="sName" required data-ng-model="Name" />
                        </td>
                    </tr>
                    <tr>
                        <td></td>
                        <td>
                            <span>Email</span>
                        </td>
                        <td>
                            <input type="text" id="sEmail" required data-ng-model="Email" />
                        </td>
                    </tr>
                    <tr>
                        <td></td>
                        <td>
                            <span>Class</span>
                        </td>
                        <td>
                            <input type="text" id="sClass" required data-ng-model="Class" />
                        </td>
                    </tr>
                    <tr>
                        <td></td>
                        <td>
                            <span>Enrollement Year</span>
                        </td>
                        <td>
                            <input type="text" id="sEnrollYear" required data-ng-model="EnrollYear" />
                        </td>
                    </tr>
                    <tr>
                        <td></td>
                        <td>
                            <span>City</span>
                        </td>
                        <td>
                            <input type="text" id="sCity" required data-ng-model="City" />
                        </td>
                    </tr>
                    <tr>
                        <td></td>
                        <td>
                            <span>Country</span>
                        </td>
                        <td>
                            <input type="text" id="sCountry" required data-ng-model="Country" />
                        </td>
                    </tr>
                    <tr>
                        <td></td>
                        <td></td>
                        <td>
                            <input type="button" id="save" value="Save" data-ng-click="save()" />
                            <input type="button" id="Clear" value="Clear" data-ng-click="clear()" />
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
</body>
</html>
<script src="~/Scripts/MyScript/Module.js"></script>

当我尝试更新记录时,这里出现了...

请任何人帮助我纠正我,我会很感激的

【问题讨论】:

Global.aspx 中缺少PUT 方法 【参考方案1】:

在您的 global.asax 中,OPTIONS 请求不返回 PUT。反过来,这会导致浏览器抢先阻止请求;

protected void Application_BeginRequest(object sender, EventArgs e)
        
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
            if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "PUT");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "DELETE");

                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
                HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
                HttpContext.Current.Response.End();
            
        

像上面一样添加 put ,我认为这将解决问题。如果没有,请检查您的 web.config 和 IIS 设置以确保没有会禁止 PUT 的设置。但是,由于错误表明飞行前响应不允许它,我很确定这只是您的 OPTIONS 请求没有声明 PUT 是允许的。

【讨论】:

以上是关于在带有 Wcf 服务的 Angular JS 的预检响应中,Access-Control-Allow-Methods 不允许方法 PUT的主要内容,如果未能解决你的问题,请参考以下文章

导入的类不能在带有 TypeScript 的 Angular.js 中用作服务

Kendo UI Angular JS 和带有服务的 AutoComplete

是否有理由在 asp.net MVC 上使用 WCF?

Angular 4 两次调用 WCF REST

Angular 4 POST 到 WCF REST 服务返回 NULL 响应

带有 Express js 的 Angular 2 cli