MVC 路由(如 WebAPI)

MVC Routing (like WebAPI)

我知道这听起来像是一个愚蠢的问题,但是有没有办法为 MVC 控制器实现 'mimic' WebAPI 路由样式(即可能使用 [HttpPost] 装饰等)。我的问题的要点是我有一个 'container' MVC 站点。这包含在 PreLoad 中加载区域文件夹中的其他 MVC 站点并将它们合并到自身中。所以它基本上充当一个插件系统。这一切都很好,但是我需要为这个站点添加一个 API,我认为如果我将 API 作为另一个插件会容易得多。

我在我的站点中使用 Ninject,这再次很好地从插件中获得了所有依赖项。问题是 Ninject 自动检测 MVC 控制器而不是 WebAPI 控制器,我发现您不能让一个项目同时使用 Nijnect 执行 WebAPI 和 MVC。所以我的下一个选择是尝试在 MVC 中模仿 WebAPI(毕竟,它们实际上基于相同的东西。)

我最初认为这会很简单,在路由中将动作名称默认为 'Index',他们只是在每个方法上放置 'AcceptVerbs' 装饰。当然没用。

有谁知道我将如何着手或仅使用 MVC 端(不切换到 WebAPI)创建类似 RestAPI 的替代方法?

您可以像往常一样使用控制器并让它们 return JsonResult。我将这种方法用于我的一些需要通过查找获得动态列表但不需要访问网络的视图 api。除了属性路由之外,我还能够从我的 MVC

中获得类似 Web api 的功能

示例场景是我有一个表单,它根据从组合框中选择的值填充一些字段。当用户选择一个选项时,我使用 JQuery 在我的控制器中调用类似 WebAPI 的操作。

[RoutePrefix("Pickup")]
[Route("{action=Create}")]
public class PickupController : FrontOfficeAuthorizedController {

    [HttpPost]
    public JsonResult GetSenderAddress(Guid? addressId) {
        if(addreddId != null) {
            //Do something to get an address

            if(address != null) {
                //Only send required info over the wire
                return Json(new {
                        success = true,
                        address = new {
                            Address1 = address.Address1,
                            Address2 = address.Address2,
                            AddressType = address.AddressType,
                            CompanyOrName = address.CompanyOrName,
                            Contact = address.Contact,
                            Country = address.Country,
                            PostalCode = address.PostalCode,
                            Telephone = address.Telephone,
                            TownCity = address.TownCity,
                        }
                });
            }
        }
        return Json(new { success = false });
    }

}

这是客户端 javascript 的片段。注意我正在使用 KnockoutJQuery

//Shipfrom properties
self.ShipFromaddressid = ko.observable();
//Update shipfrom address based on id
self.ShipFromaddressid.subscribe(function () { getAddress(); });


var getAddress = function () {
    var selectedAddressId = { addressId: self.ShipFromaddressid() };
    $.ajax({
        url: '@(Url.Action<PickupController>(c=>c.GetSenderAddress(null)))',
        type: 'Post',
        contentType: 'application/json',
        dataType: 'json',
        data: JSON.stringify(selectedAddressId),
        success: handleResponse
    });
};

var handleResponse = function (data) {
    if (data.success) {
        //console.log(data.address);
        self.ShipFromCompanyOrName((data.address.CompanyOrName) ? data.address.CompanyOrName : "");
        self.ShipFromContact((data.address.Contact) ? data.address.Contact : "");
        self.ShipFromTelephone((data.address.Telephone) ? data.address.Telephone : "");
        self.ShipFromAddress1((data.address.Address1) ? data.address.Address1 : "");
        self.ShipFromAddress2((data.address.Address2) ? data.address.Address2 : "");
        self.shipfromtowncity((data.address.TownCity) ? data.address.TownCity : "");
        self.ShipFromPostalCode((data.address.PostalCode) ? data.address.PostalCode : "");
        self.ShipFromCountry((data.address.Country) ? data.address.Country : "");
        self.ShipFromAddressType((data.address.AddressType) ? data.address.AddressType : "");
    }
};

在您的 RouteConfig.cs 文件中,您可以通过传递 HttpMethodContraint 指定哪个 HTTP 谓词转到哪个操作:

routes.MapRoute(
"route that matches only GETs for your url",
"your url",
new { controller = "some controller", action = "some action" },
new { httpMethod = new HttpMethodConstraint("GET") });

这将允许您定义到模仿 WebAPI 的控制器的路由。