Javascript 在Angular和.Net MVC 5/Web API中使用http.delete

Javascript 在Angular和.Net MVC 5/Web API中使用http.delete,javascript,angularjs,asp.net-web-api,asp.net-mvc-5,http-delete,Javascript,Angularjs,Asp.net Web Api,Asp.net Mvc 5,Http Delete,使用WebApi和MVC 5和 AngularJS 1.3.4版 我有一个API设置,它有一个收藏夹repository&ifavoriterepository&Ninject。这部分没问题,我可以通过UserId或SearchId检索收藏夹。我的收藏夹列表是围绕Search.cs模型构建的API: namespace RenderLib.Models { public class Search { public int SearchId { get; set; } [M

使用WebApi和MVC 5和
AngularJS 1.3.4版

我有一个API设置,它有一个
收藏夹repository
&
ifavoriterepository
&Ninject。这部分没问题,我可以通过UserId或SearchId检索收藏夹。我的收藏夹列表是围绕
Search.cs
模型构建的API:

namespace RenderLib.Models
{
  public class Search
  {
    public int SearchId { get; set; }
    [MaxLength(128), Column(TypeName = "nvarchar")]
    public string UserId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public DateTime? Created { get; set; }
    [MaxLength(2080), Column(TypeName = "nvarchar")]
    public string SearchString { get; set; }
  }
}
在我的数据层目录中,我有
FavoritesRepository
ifavoiritesrepository
,使用以下添加和删除方法。
(添加方法适用于Angular just fine):

/DataLayer/IFavoritesRepository.cs

namespace RenderLib.DataLayer
{
  public interface IFavoritesRepository
  {
    IQueryable<Search> GetFavoritesByUserId(string id);
    IQueryable<Search> GetFavoriteBySearchId(int id);

    bool Save();
    bool AddFavorite(Search newSearch);
    bool DelFavorite(int id);
  }
}
namespace RenderLib.DataLayer
{
  public class FavoritesRepository : IFavoritesRepository
  {
    RenderLibContext _ctx;
    public FavoritesRepository(RenderLibContext ctx)
    {
      _ctx = ctx;
    }


    public IQueryable<Search> GetFavoritesByUserId(string id)
    {
      return _ctx.Search.Where(s => s.UserId == id);
    }

    public IQueryable<Search> GetFavoriteBySearchId(int id)
    {
      return _ctx.Search.Where(s => s.SearchId == id);
    }


    public bool Save()
    {
      try
      {
        return _ctx.SaveChanges() > 0;
      }
      catch
      {
        // TODO log this error
        return false;
      }
    }

    public bool AddFavorite(Search newFavorite)
    {
      _ctx.Search.Add(newFavorite);
      return true;
    }

    public bool DelFavorite(int id)
    {
      var search = _ctx.Search;
      search.Remove(search.SingleOrDefault(s => s.SearchId == id));
      return true;
    }
  }
}
public class FavoritesController : ApiController
{
    private IFavoritesRepository _favRepo;
    public FavoritesController(IFavoritesRepository favRepo)
    {
        _favRepo = favRepo;
    }

    public IEnumerable<Search> Get()
    {
        var id = User.Identity.GetUserId();
        IQueryable<Search> results; 
        results = _favRepo.GetFavoritesByUserId(id);

        var favorites = results.OrderByDescending(s => s.UserId == id);

        return favorites;
    }

    public HttpResponseMessage Post([FromBody]Search newFavorite)
    {
        if (newFavorite.Created == null)
        {
            newFavorite.Created = DateTime.UtcNow;
        }

        if (_favRepo.AddFavorite(newFavorite) && _favRepo.Save())
        {
            return Request.CreateResponse(HttpStatusCode.Created, newFavorite);
        }
        return Request.CreateResponse(HttpStatusCode.BadRequest);
    }

    public HttpResponseMessage Delete(Search id)
    {
        if (_favRepo.DelFavorite(id) && _favRepo.Save())
        {
            return Request.CreateResponse(HttpStatusCode.Created, id);
        }
        return Request.CreateResponse(HttpStatusCode.BadRequest);
    }
}
angular
    .module("renderIndex", ["ngRoute","ngCookies"])
    .config(config)
    .controller("favoritesController", favoritesController)
    .controller("newFavoriteController", newFavoriteController);

function config($routeProvider) {
    $routeProvider
        .when("/", {
            templateUrl: "/ng-templates/favoritesView.html",
            controller: "favoritesController",
            controllerAs: "vm"
        })
        .when("/newfavorite", {
            templateUrl: "/ng-templates/newFavoriteView.html",
            controller: "newFavoriteController",
            controllerAs: "vm"
        })
        .otherwise({ redirectTo: "/" });
};

function favoritesController($http) {
    var vm = this;
    vm.searches = [];
    vm.isBusy = true;

    $http.get("/api/favorites")
        .success(function (result) {
            vm.searches = result;
        })
        .error(function () {
            alert('error/failed');
        })
        .then(function () {
            vm.isBusy = false;
        });

    vm.delete = function (searchId) {
        var url = "/api/favorites/" + searchId;
        $http.delete(url)
            .success(function (result) {
                var newFavorite = result.data;
                //TODO: merge with existing topics
                alert("Delete Successfull");
                removeFromArray(vm.searches, searchId);
            })
            .error(function () {
                alert("Your broken, go fix yourself!");
            })
            .then(function () {
                $window.location = "#/";
            });
    };
};

function removeFromArray(items, searchId) {
    var index;
    for (var i = 0; i < items.length; i++) {
        if (items[i].searchId == searchId) {
            index = i;
            break;
        }
    }
    if (index) {
        items.splice(index, 1);
    }
}

function newFavoriteController($http, $window, $cookies) {
    var vm = this;
    vm.newFavorite = {};
    vm.newFavorite.searchString = $cookies.currentSearch;
    vm.newFavorite.userId = $cookies.uId;
    vm.save = function () {
        $http.post("/api/favorites", vm.newFavorite)
            .success(function (result) {
                var newFavorite = result.data;
                //TODO: merge with existing topics
                alert("Thanks for your post");
            })
            .error(function () {
                alert("Your broken, go fix yourself!");
            })
            .then(function () {
                $window.location = "#/";
            });
    };
};
/ng templates/newFavoriteView.html
路线:#/newfavorite

<div class="small-12 column"><h3>Saving Search</h3></div>
<div class="small-12 column">
    <form name="newFavoriteForm" novalidate ng-submit="vm.save()">
        <input name="userId" type="hidden" 
               ng-model="vm.newFavorite.userId" />
        <input name="searchString" type="hidden" 
               ng-model="vm.newFavorite.searchString" />
        <label for="name">Name</label>
        <input name="name" type="text" 
               ng-model="vm.newFavorite.name" autofocus/>
        <label for="description">Description</label>
        <textarea name="description" rows="5" cols="30" 
                  ng-model="vm.newFavorite.description"></textarea>
        <input type="submit" class="tiny button radius" value="Save" /> | 
        <a href="#/" class="tiny button radius">Cancel</a>
    </form>
</div>

调用delete函数。Omri不仅帮助我了解了如何将参数传递给函数的概念,还帮助我编写了一个函数来更新视图以显示删除的项。我非常感谢他的帮助。如果您觉得这很有用,请1给出他的答案。

我将总结为一个答案,因为评论太忙了:)

由于视图中有
ng model=“vm.newFavorite.searchId”
,因此您可以获取您的searchId并使用它附加到url:

vm.delete = function (searchId) {

    //API Controller will expect "/api/favorites/13" from an http delete

    var url = "/api/favorites/" + searchId;
    $http.delete(url)
        .success(function (result) {
            var newFavorite = result.data;
            //TODO: merge with existing topics
            alert("Delete Successfull");
            removeFromArray(vm.searches, searchId);
        })
        .error(function () {
            alert("Your broken, go fix yourself!");
        })
        .then(function () {
            $window.location = "#/";
        });
};
})

请注意,
FavoritesController
中的
Delete
函数现在只需要一个
searchId
参数,因此您需要更改客户端或服务器上的名称,以便它们匹配,您肯定需要将服务器中变量的类型从
Search
更改为string或Guid


编辑:在一次聊天讨论后,我们得出结论,删除表单元素,只需一个按钮,然后单击删除功能。

对我有效的操作:将
$http.delete(“/api/favorites”,vm.delFavorite”)
更改为
$http[“delete”](“/api/favorites”,vm.delFavorite)
顺便说一句,我只使用没有数据的URL,如果你使用数据,我认为它需要作为对象发送。是的,正如你所看到的,我是从Add/Post函数复制的,所以也许我应该只发送一个参数而不是对象,我真的在寻找一些关于最简单方法的建议。我会研究你的想法并继续研究,但我的问题是最终的解决方案。我不确定是我太累了,还是我只是错过了一个简单的概念,这让我被阻止了。是的,如果你有一个对象的标识符,
$http.delete(url)
,其中url包含标识符应该是正确的选择。标识符是searchId。我假设我可以把它从视图中拉出来并传递给控制器,但我不确定具体怎么做。我是传递对象还是只传递id?我们将对象传递到视图并在其上重复的控制器中的语法,以及如何将该id返回到delete方法中?我不知道该怎么做。我希望我使用的教程能够对此有所了解。但是他们让我在我到达终点之前就被绞死了,但是我知道我已经很接近了。让我来做这个。如果遇到任何问题,我将更新源代码。我已更新了
FavoritesRepository.cs
中的DelFavorite和控制器中的
vm.delete()
函数。现在它更有意义了。但是我应该把
searchId
放在表单的哪里呢?我应该能够从{s.searchId}中获取它,但是我如何将它传递回vm.delete()函数,该函数将它传递给WebApi控制器?@EricB您可以将它修改为
ng click=“vm.delete({s.searchId}”)
,然后更新函数以接收参数。您能否查看我的视图和控制器,并告诉我语法是否正确?如果您想绕过
WebApi
所期望的
/id
,我只是在上面更新了它。然后您需要在WebApi控制器中声明删除操作:
[FromUri]int searchId
<a href="javascript:void(0);" ng-click="vm.delete(s.searchId)">X</a>
vm.delete = function (searchId) {

    //API Controller will expect "/api/favorites/13" from an http delete

    var url = "/api/favorites/" + searchId;
    $http.delete(url)
        .success(function (result) {
            var newFavorite = result.data;
            //TODO: merge with existing topics
            alert("Delete Successfull");
            removeFromArray(vm.searches, searchId);
        })
        .error(function () {
            alert("Your broken, go fix yourself!");
        })
        .then(function () {
            $window.location = "#/";
        });
};