剃刀页面和webapi在同一项目中

时间:2019-05-24 19:41:59

标签: asp.net-core

我在.net core 3.0中创建了一个Web应用程序(剃须刀页面)。然后,我向其中添加了一个api控制器(均来自模板,只需单击几下)。当我运行应用程序时,剃须刀页面有效,但api调用返回404。问题出在哪里,如何使它起作用?

3 个答案:

答案 0 :(得分:4)

除了 the answer of @Ryan 之外,我还必须添加一个带有控制器/操作模式的默认路由。否则无法访问控制器,直到我在其上设置 [Route("example")] 装饰器。由于我更喜欢​​像在 MVC 中一样生成基于模式的路由,因此我在 Startup.Configure 中定义了默认路由,如下所示:

app.UseEndpoints(endpoints => {
    endpoints.MapRazorPages();
    endpoints.MapControllerRoute("default", "api/{controller=Home}/{action=Index}/{id?}");
    endpoints.MapControllers();
});

有一个名为 CommunityController 的控制器,您现在可以在 /api/community/index 处到达索引操作,或者只使用简短的形式 /api/community 因为 index 被定义为默认操作在路线中。

此外,仍然需要在 ConfigureServices 方法中添加控制器组件,如@Ryan 所示:

public void ConfigureServices(IServiceCollection services) {
    services.AddRazorPages();
    services.AddControllers();
    // ...
}

使用 ASP.NET Core 3.1 Razor 页面进行测试。

答案 1 :(得分:0)

您需要将启动配置为支持Web API和属性路由。

<textarea oninput="scrollMe()" id="wordMe"></textarea> <iframe id="iframeScroll" srcdoc=""></iframe>添加了对控制器和API相关功能的支持,但不支持视图或页面。请参阅MVC service registration

如果应用程序使用属性路由,则添加services.AddControllers()。请参阅Migrate MVC controllers

合并剃须刀页面和api之类的

endpoints.MapControllers

答案 2 :(得分:0)

将WebApi添加到现有的dot net core 2剃刀页面应用程序并配置身份验证方案。 如果您打算在.net Web应用程序中添加webapi,则将需要为您的应用程序配置两种身份验证方案,例如JWT令牌身份验证以保护webapi和cookie身份验证网页。

要添加Web api,请进入控制器部分,并创建一个名为Api的新文件夹,并在其中创建一个新的控制器,例如OrderController

添加控制器后,您必须为所有api请求调用指定身份验证方案(例如JWT)和路由路径前缀(例如“ api /”)。

控制器代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using ApplicationCore.Entities.OrderAggregate;
using Infrastructure.Data;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication.JwtBearer;

namespace WebRazorPages.Controllers.Api
{
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Produces("application/json")]
[Route("api/Orders")]
public class OrdersController : Controller
{
    private readonly ProductContext _context;

    public OrdersController(ProductContext context)
    {
        _context = context;
    }

    // GET: api/OrdersApi
    [HttpGet]
    public IEnumerable<Order> GetOrders()
    {
        return _context.Orders;
    }

    // GET: api/OrdersApi/5
    [HttpGet("{id}")]
    public async Task<IActionResult> GetOrder([FromRoute] int id)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var order = await _context.Orders.SingleOrDefaultAsync(m => m.Id == id);

        if (order == null)
        {
            return NotFound();
        }

        return Ok(order);
    }

    // PUT: api/OrdersApi/5
    [HttpPut("{id}")]


public async Task<IActionResult> PutOrder([FromRoute] int id, [FromBody] Order order)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

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

        _context.Entry(order).State = EntityState.Modified;

        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!OrderExists(id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return NoContent();
    }

    // POST: api/OrdersApi
    [HttpPost]
    public async Task<IActionResult> PostOrder([FromBody] Order order)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        _context.Orders.Add(order);
        await _context.SaveChangesAsync();

        return CreatedAtAction("GetOrder", new { id = order.Id }, order);
    }

    // DELETE: api/OrdersApi/5
    [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteOrder([FromRoute] int id)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var order = await _context.Orders.SingleOrDefaultAsync(m => m.Id == id);
        if (order == null)
        {
            return NotFound();
        }

        _context.Orders.Remove(order);
        await _context.SaveChangesAsync();

        return Ok(order);
    }

    private bool OrderExists(int id)
    {
        return _context.Orders.Any(e => e.Id == id);
    }
}
}

启动配置: 首先,您必须在Startup.cs中添加身份验证方案配置 您必须同时添加cookie和jwt令牌配置,但是您可以选择任何一种作为默认方案,在这种情况下,我们必须选择cookie方案作为默认方案,将其应用于所有方案而无需显式指定,要在webapi上使用jwt方案,我们必须明确指定。

添加身份

services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ProductContext>()
            .AddDefaultTokenProviders();

配置Cookie

services.ConfigureApplicationCookie(options =>
        {
            options.Cookie.HttpOnly = true;
            options.ExpireTimeSpan = TimeSpan.FromHours(1);
            options.LoginPath = "/Account/Signin";
            options.LogoutPath = "/Account/Signout";
        });
        services.AddAuthentication(
        options =>
        {
            options.DefaultScheme =  CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        })
        .AddCookie()
        .AddJwtBearer(config =>
        {

            config.RequireHttpsMetadata = false;
            config.SaveToken = true;

            config.TokenValidationParameters = new TokenValidationParameters()
            {
                ValidIssuer = Configuration["jwt:issuer"],
                ValidAudience = Configuration["jwt:issuer"],
                IssuerSigningKey = new  SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["jwt:key"]))
            };
        });
       
        services.Configure<JwtOptions>(Configuration.GetSection("jwt"));