Knockout + Asp.Net MVC Core 2.2的Url.Action错误

时间:2019-05-03 12:03:51

标签: knockout.js asp.net-core-mvc asp.net-core-2.0

我正在尝试生成一个表,其中包含具有剔除和Asp.Net Core 2.2的每一行的链接。实际上,我希望以后可以单击整行,但在此示例中,我还是将其添加为表字段。

@Url.Action("MyAction", "My")的路径生成错误。他们两个都是空的。控制器和操作都不会出现在生成的链接中。

<tbody data-bind="foreach: searchResults">
  <tr>
    <td data-bind="text: id"></td>
    <td>
      <a data-bind="attr: { href: '@Url.Action("MyAction", "My")/' + id}">
        Click
      </a>
    </td>
    <td data-bind="text: name"></td>
    <td data-bind="text: date"></td>
  </tr>
</tbody>

“我的”是控制器“ MyController”。 “ MyAction”是我要在单击时调用的操作方法的名称。我确实有另一个控制器,用于不同的路径。我要使用的是这样的:

[Route("api/[controller]")]
[ApiController]
public class MyController : ControllerBase
{
    private readonly IWebServiceFactory webServiceFactory;

    public MyController(IWebServiceFactory webServiceFactory)
    {
        this.webServiceFactory = webServiceFactory;
    }

    // GET: api/MyAction/{GUID}
    [HttpGet("{id:Guid}")]
    public async Task<IActionResult> MyAction(Guid id)
    {
        var result = await webServiceFactory.GetWebService().GetFileAsync(id);
        var memory = new MemoryStream();
        await result .Stream.CopyToAsync(memory);
        memory.Position = 0;
        return File(memory, "application/unknown", result.FileName);
    }
}

我想也许是因为控制器路由没有使用任何动作,但是即使在将动作添加到路由之后,结果也是相同的。

我将Mvc与Startup.cs中的默认路由一起使用:

app.UseMvcWithDefaultRoute();

这是我得到的实际输出:

<a data-bind="attr: { href: '/' + id }" href="/173a4cec-a258-4ebb-d28e-08d6cee0966c">Click</a>

我在做什么错了?

1 个答案:

答案 0 :(得分:1)

为避免Url.Action尝试呈现与MVC视图相关的网址,而不是Api端点网址,
@Url.RouteUrl与已应用于给定Api控制器操作方法的路由名称一起使用;例如。 ApiMyMyActionGuidRoute

[Route("api/[controller]")]
[ApiController]
public class MyController : ControllerBase
{   
    [HttpGet("{id:Guid}", Name ="ApiMyMyActionGuidRoute")]
    public async Task<IActionResult> MyAction(Guid id)
    {
        // Your implementation goes here ...
    }
}

在您看来,通过@Url.Route呈现网址。
请注意,您必须为Guid参数应用虚拟id值,因为此参数在操作方法(MyAction(Guid id))上是必需的。

由于此id值是通过Knockout绑定应用的,因此在将其应用于Knockout data-bind之前,您首先必须从生成的url中删除一个虚拟对象表达。

@{  
    var routeUrl = Url.RouteUrl("ApiMyMyActionGuidRoute", new { id = Guid.Empty });
    // routeUrl = "/api/My/00000000-0000-0000-0000-000000000000"
    routeUrl = routeUrl.Substring(0, routeUrl.LastIndexOf("/"));
    // routeUrl = "/api/My"
}
<p><a data-bind="attr: { href: '@routeUrl/' + id }">Click</a></p>

这将在下面生成具有正确Api端点url的html标记,Knockout将在id上应用参数<p><a data-bind="attr: { href: '/api/My/' + id }">Click</a></p>

v1  v2  v3
M   Z   P
Z   Z   P
P   Z   M
Z   P   Z