转换Asp的最佳方法。Net MVC控制器到Web API

时间:2021-12-21 20:07:49

I have this ASP.NET MVC 5 project which I'm converting over to AngularJS with MS Web Api.

我有一个ASP。NET MVC 5项目我用MS Web Api把它转换成AngularJS。

Now in the old project I have these c# controllers of type Controller, however in my new project I've created some new Web Api controllers of type ApiController.

在以前的项目中,我有这些c#控制器的类型,但是在我的新项目中,我创建了一些新的ApiController类型的Web Api控制器。

Now I'd like to reuse the old controller code in my new project. Herein lies my confusion.

现在我想在我的新项目中重用旧的控制器代码。这就是我的困惑。

As I attempt to port the old controller code over to my Web Api controller, I'm getting some front-end $http request errors.

当我尝试将旧的控制器代码移植到我的Web Api控制器时,我得到了一些前端的$http请求错误。

Here's a function from my Angular dataService factory which makes an http req down to 'api/Whatif/SummaryPortfolios':

这是我的数据工厂的一个函数,它使http req降低到“api/Whatif/ summary组合”:

function getCurrPortfoliosLIst() {
  var deferred = $q.defer();

  var url = 'api/Whatif/SummaryPortfolios';
  var req={
    method: 'POST',
    url: url,
    headers: {
      'Content-Type': 'application/json',
    },
    data:{}
  };
  $http(req).then(function (resp){
    deferred.resolve(resp.data);
  }, function(err){
    console.log('Error from dataService: ' + resp);
  });
}

But the $http error section is returning this exception:

但是$http错误部分返回这个异常:

data: Object
ExceptionMessage: "Multiple actions were found that match the request: 
↵SummaryPortfolios on type MarginWorkbenchNG.Controllers.WhatifController
↵Post on type MarginWorkbenchNG.Controllers.WhatifController"
ExceptionType: "System.InvalidOperationException"
Message: "An error has occurred."
StackTrace: "   at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)
↵   at System.Web.Http.Controllers.ApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)
↵   at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
↵   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()

Here's the c# API controller I'm calling down to, but I need to figure out how to create methods other than straight Get() and Post() methods:

下面是我要调用的c# API控制器,但是我需要知道如何创建除了直接Get()和Post()方法之外的其他方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using Microsoft.AspNet.Identity;
using NLog;
using Microsoft.AspNet.Identity.Owin;
using MarginWorkbenchNG.Models;
using Rz.DAL;
using Rz.DAL.Integration;
using Rz.DAL.Models;
using Rz.DAL.Models.Rz;

namespace MarginWorkbenchNG.Controllers
{
    public class WhatifController : ApiController
    {
		public IEnumerable<string> Get()
			{						 
				return new string[] { "value1", "value2" };
			}
		[HttpPost]
        public List<WhatifSummaryViewModel> SummaryPortfolios(string filterValue = "", int? whatIfBatchNumber = null, bool includeBaseline = true)
        {
            // Get portfolios from Rz
            IEnumerable<Portfolio> portfolios = GetPortfolios(filterValue, whatIfBatchNumber, includeBaseline)
                .Where(x => x.PortfolioKeys.Any(k => k.Type == Settings.Whatif.SidebarPortfolioKey && k.DisplayValue == filterValue));

            // View Model
            List<WhatifSummaryViewModel> model = new List<WhatifSummaryViewModel> { };

            /// additional code here...

            return model;
        }
	}
}

The old controller (from the MVC5 project) looks slightly different of course because the _Summary method is of type ActionResult and returns a Partial:

旧的控制器(来自MVC5项目)当然看起来有点不同,因为_Summary方法是ActionResult类型,并返回一个部分:

public class WhatifController : Controller
    {
      
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult _Summary(string filterValue = "", int? whatIfBatchNumber = null, bool includeBaseline = true)
        {
            // Get portfolios from Razor
            IEnumerable<Portfolio> portfolios = GetPortfolios(filterValue, whatIfBatchNumber, includeBaseline)
                .Where(x => x.PortfolioKeys.Any(k => k.Type == Settings.Whatif.SidebarPortfolioKey && k.DisplayValue == filterValue));

            // View Model
            List<WhatifSummaryViewModel> model = new List<WhatifSummaryViewModel> { };

           // additional code removed for brevity...

            return PartialView(model.OrderBy(x => x.Title).ThenBy(x => x.SubTitle));
        }

My RouteConfig.cs :

我的RouteConfig。cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MarginWorkbenchNG
{
  public class RouteConfig
  {
    public static void RegisterRoutes(RouteCollection routes)
    {
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

      routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
      );
    }
  }
}

The old project also uses Html forms to pull the URL, for example:

旧的项目也使用Html表单来提取URL,例如:

 <form id="whatif-summary-form" action="@Url.Action("_Summary", "WhatIf")" method="POST"></form>

and then pulls the action attrib to get the URL when building out the ajax request in JavaScript (non-Angular) :

然后拉attrib动作获取JavaScript构建ajax请求时的URL(非角):

url: form.prop("action")

1 个解决方案

#1


1  

Is this your entire ApiController? The error message you are receiving is because your ApiController has several methods that are of the same type and it can't tell which one to route to. To test this: comment out all of your controller's methods except the one you are calling. You shouldn't receive that error anymore.

这是你的全部ApiController吗?您正在接收的错误消息是由于ApiController有几个类型相同的方法,它不能告诉要路由到哪个方法。要测试这一点,请注释掉除正在调用的方法之外的所有控制器方法。你不应该再收到那个错误。

This is an easy fix, just tell web api how to map your route. Add the attribute '[Route("yourroute')]' to your method and it should work.

这是一个简单的修复,只需告诉web api如何映射您的路由。将属性'[Route("yourroute ")]'添加到方法中,它应该可以工作。

    public class WhatifController : ApiController
    {
        [HttpPost, Route("Your Route Goes here 'SummaryPortfolios'")]
        public IHttpActionResult SummaryPortfolios(string filterValue = "", int? whatIfBatchNumber = null, bool includeBaseline = true)
        {
            // Get portfolios from Rz
            IEnumerable<Portfolio> portfolios = GetPortfolios(filterValue, whatIfBatchNumber, includeBaseline)
                .Where(x => x.PortfolioKeys.Any(k => k.Type == Settings.Whatif.SidebarPortfolioKey && k.DisplayValue == filterValue));

            // View Model
            List<WhatifSummaryViewModel> model = new List<WhatifSummaryViewModel> { };

            /// additional code here...

            return Ok(model);
        }
    }

#1


1  

Is this your entire ApiController? The error message you are receiving is because your ApiController has several methods that are of the same type and it can't tell which one to route to. To test this: comment out all of your controller's methods except the one you are calling. You shouldn't receive that error anymore.

这是你的全部ApiController吗?您正在接收的错误消息是由于ApiController有几个类型相同的方法,它不能告诉要路由到哪个方法。要测试这一点,请注释掉除正在调用的方法之外的所有控制器方法。你不应该再收到那个错误。

This is an easy fix, just tell web api how to map your route. Add the attribute '[Route("yourroute')]' to your method and it should work.

这是一个简单的修复,只需告诉web api如何映射您的路由。将属性'[Route("yourroute ")]'添加到方法中,它应该可以工作。

    public class WhatifController : ApiController
    {
        [HttpPost, Route("Your Route Goes here 'SummaryPortfolios'")]
        public IHttpActionResult SummaryPortfolios(string filterValue = "", int? whatIfBatchNumber = null, bool includeBaseline = true)
        {
            // Get portfolios from Rz
            IEnumerable<Portfolio> portfolios = GetPortfolios(filterValue, whatIfBatchNumber, includeBaseline)
                .Where(x => x.PortfolioKeys.Any(k => k.Type == Settings.Whatif.SidebarPortfolioKey && k.DisplayValue == filterValue));

            // View Model
            List<WhatifSummaryViewModel> model = new List<WhatifSummaryViewModel> { };

            /// additional code here...

            return Ok(model);
        }
    }