简体   繁体   English

调用Web API时$ http调用两次

[英]$http call twice when calling web api

I have create a WEB API using ASP.NET MVC WEB API 2.0 . 我已经使用ASP.NET MVC WEB API 2.0创建了WEB API Web API contain methods like login , register , etc. Web API包含诸如loginregister等方法。
I am using AngularJS to call the WEB API methods, But it call twice. 我正在使用AngularJS调用WEB API方法,但是它调用了两次。 For eg when I call POST method it first call OPTION (I have not created any OPTION method) and then it call the POST method. 例如,当我调用POST方法时,它首先调用OPTION (我还没有创建任何OPTION方法),然后又调用POST方法。
My Code: (for login) 我的代码:(用于登录)
HTML: HTML:

<div class="container" ng-controller="UserAccount">
    <form ng-submit="loginNow(user)">
        <input type="email" placeholder="Enter Email" required ng-model="user.email" id="txtEmail" class="form-control" />
        <br />
        <input type="password" placeholder="Enter Password" required ng-model="user.password" id="txtPwd" class="form-control" />
        <br />
        <button type="submit" class="btn btn-primary">Login</button>
    </form>
</div>


AngularJS Controller: AngularJS控制器:

$scope.loginNow = function (user) {
        $http.post(rootURL + "login", { email: user.email, password: user.password })
            .success(function (data) {
                if (data.id > 0) {
                    sessionStorage.setItem('userid', data.id);
                    window.location = '/';
                }
            });
}


WEB API: WEB API:

public class UsersController : ApiController
    {
        private UserEntities db = new UserEntities();

        // GET: api/Users
        public IQueryable<Users_tbl> GetUsers_tbl()
        {
            return db.Users_tbl;
        }

        [ActionName("login")]
        public IHttpActionResult PostUser_Login(string email, string password)
        {
            int id = db.Users_tbl.Where(a => a.email == email && a.password == password).Select(a => a.id).SingleOrDefault();
            if(id <= 0)
            {
                return NotFound();
            }
            return Ok(id);
        }

        [ActionName("register")]
        public int PostUser_Register(string email, string password)
        {
            int id = db.Users_tbl.Where(a => a.email == email).Select(a => a.id).SingleOrDefault();
            if(id > 0)
            {
                return 1;
            }
            Users_tbl user = new Users_tbl();
            user.email = email;
            user.password = password;
            try
            {
                db.Users_tbl.Add(user);
                db.SaveChanges();
            }
            catch
            {
                return 2;
            }
            return 0;
        }


        // GET: api/Users/5
        [ResponseType(typeof(Users_tbl))]
        public IHttpActionResult GetUsers_tbl(int id)
        {
            Users_tbl users_tbl = db.Users_tbl.Find(id);
            if (users_tbl == null)
            {
                return NotFound();
            }

            return Ok(users_tbl);
        }


        // PUT: api/Users/5
        [ResponseType(typeof(void))]
        public IHttpActionResult PutUsers_tbl(int id, Users_tbl users_tbl)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            if (id != users_tbl.id)
            {
                return BadRequest();
            }

            db.Entry(users_tbl).State = EntityState.Modified;

            try
            {
                db.SaveChanges();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!Users_tblExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return StatusCode(HttpStatusCode.NoContent);
        }

        [ActionName("profile")]
        // POST: api/Users
        [ResponseType(typeof(Users_tbl))]
        public IHttpActionResult PostUsers_tbl(Users_tbl users_tbl)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            db.Users_tbl.Add(users_tbl);
            db.SaveChanges();

            return CreatedAtRoute("DefaultApi", new { id = users_tbl.id }, users_tbl);
        }

        // DELETE: api/Users/5
        [ResponseType(typeof(Users_tbl))]
        public IHttpActionResult DeleteUsers_tbl(int id)
        {
            Users_tbl users_tbl = db.Users_tbl.Find(id);
            if (users_tbl == null)
            {
                return NotFound();
            }

            db.Users_tbl.Remove(users_tbl);
            db.SaveChanges();

            return Ok(users_tbl);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }

        private bool Users_tblExists(int id)
        {
            return db.Users_tbl.Count(e => e.id == id) > 0;
        }
    }

This is the browser default behavior. 这是浏览器的默认行为。 Before sending corss-domain AJAX call, browser sends a pre-flight request ( OPTION request) Why? 在发送corss域AJAX调用之前,浏览器会发送飞行前请求OPTION请求), 为什么?

Have a look over here on how you can minimize pre-flight request: 这里查看如何最小化飞行前请求:

Update 更新资料

If you really want not to send pre-flight request, you can opt by not violating Same Origin Policy (SOP). 如果您确实不希望发送飞行前请求,则可以选择不违反相同原点策略(SOP)。 Possible solution can be: 可能的解决方案可以是:

JSONP : This is a technique that exploits the HTML script element exception to the same-origin security policy. JSONP这是一种将HTML脚本元素异常用于同源安全策略的技术。 Script tags can load JavaScript from a different domain and query parameters can be added to the script URI to pass information to the server hosting the script about the resources that you wish to access. 脚本标记可以从其他域加载JavaScript,并且可以将查询参数添加到脚本URI,以将有关您希望访问的资源的信息传递到托管脚本的服务器。 The JSONP server will return JavaScript that is evaluated in the browser that calls an agreed upon JavaScript function already on the page to pass server resource data into your page. JSONP服务器将返回在浏览器中评估的JavaScript,该浏览器将调用页面上已有的JavaScript函数,以将服务器资源数据传递到页面中。

Server Side Proxy: An alternative to circumventing the Same-Origin Policy to perform Cross-Domain requests is to simply not make any Cross-Domain requests at all! 服务器端代理:绕过执行跨域请求的“同源策略”的一种替代方法是根本不发出任何跨域请求! If you use a proxy that resides in your domain, you can simply use this to access the external service from your back-end code and forward the results to your client code. 如果您使用的是位于您域中的代理,则只需使用它即可从后端代码访问外部服务,并将结果转发给客户代码。 Because the requesting code and the proxy reside in the same domain, the SOP is not violated. 由于请求代码和代理位于同一域中,因此不会违反SOP。

UPDATE You can respond to OPTIONS request from Web API 2 so that doesn't throw 405 or 404. Have a look over here https://stackoverflow.com/a/37425746/2509344 更新您可以响应来自Web API 2的OPTIONS请求,因此不会抛出405或404。请在此处查看https://stackoverflow.com/a/37425746/2509344

发生这种情况的原因是,无论何时页面加载时,在初始化期间都发生一次,然后当您按Login时,它将再次调用。

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

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