我正在做一个ASP。. NET Core应用程序。它的一部分是一个图片库,允许用户上传图像。在本地主机上,这按预期工作,但当我部署(AWS Lambda与API网关)的上传按钮缺少asp-controller
属性。
我有一个GalleryController.cs
有两个方法:
public async Task<IActionResult> Index()
{
// Pulls images from aws S3, adds them to a list and passes them to then returns View();
}
[HttpPost("Upload")]
public async Task<IActionResult> Upload(List<IFormFile> files)
{
// For each iformFile in Files, create a thumbnail in memory then upload both the original and thumbnail to aws s3 bucket
return RedirectToAction("Index");
}
我的startup.cs
中的路由配置已从样板中保留默认值:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
Views
的文件夹结构如下:
├── Views
│ ├── Gallery
│ │ ├── _GalleryPartial.cshtml
│ │ ├── Index.cshtml
│ │ └── _UploadPartial.cshtml
│ ├── Home
│ │ └── Index.cshtml
_UploadPartial。CSHTML看起来像这样:
<div class="container">
<div class="col-md-12">
<form method="post" enctype="multipart/form-data" asp-controller="Gallery" asp-action="Upload">
<div class="form-group">
<div class="col-md-12">
<div class="col-md-6">
<input class="form-control-file" type="file" name="files" multiple />
</div>
<div class="col-md-6">
<input class="form-control-file" type="submit" value="Upload" />
</div>
</div>
</div>
</form>
</div>
</div>
<hr>
正如你所看到的,我有asp-controller="Gallery"
和asp-action="Upload"
,但是当我检查表单部署到lambda后,它似乎忽略了控制器标签。
看起来我没有足够的点来嵌入图像,所以创建了一个链接
edit根据要求,以下是Gallery/index.cshtml
@model Dictionary<string, string>
@{
ViewData["Title"] = "News page";
}
<center>
@await Html.PartialAsync("_uploadPartial")
@await Html.PartialAsync("_galleryPartial")
</center>
和startup.cs
的内容:
using Amazon.S3;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Redacted.Helpers;
namespace Redacted;
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews().AddRazorRuntimeCompilation();
services.AddAWSService<IAmazonS3>();
services.AddTransient<ImageHelper>();
services.AddRazorPages();
services.AddMvcCore();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
// Signin:
options.ResponseType = Environment.GetEnvironmentVariable("ResponseType");
options.MetadataAddress = Environment.GetEnvironmentVariable("MetadataAddress");
options.ClientId = Environment.GetEnvironmentVariable("ClientId");
options.ClientSecret = Environment.GetEnvironmentVariable("ClientSecret");
// Signout
options.Events = new OpenIdConnectEvents()
{
OnRedirectToIdentityProviderForSignOut = OnRedirectToIdentityProviderForSignOut
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("Admins", policy => policy.RequireAssertion(context => context.User.HasClaim(c => c.Type == "cognito:groups" && c.Value == "admins")));
options.AddPolicy("Users", policy => policy.RequireAssertion(context => context.User.HasClaim(c => c.Type == "cognito:groups" && c.Value == "users" || c.Value == "admins")));
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
private Task OnRedirectToIdentityProviderForSignOut(RedirectContext context)
{
context.ProtocolMessage.Scope = "openid";
context.ProtocolMessage.ResponseType = "code";
var cognitoDomain = Environment.GetEnvironmentVariable("CognitoDomain");
var clientId = Environment.GetEnvironmentVariable("ClientId");
var logoutUrl = Environment.GetEnvironmentVariable("LogoutUri");
context.ProtocolMessage.IssuerAddress = $"{cognitoDomain}/logout?client_id={clientId}&logout_uri={logoutUrl}&redirect_uri={logoutUrl}";
// delete cookies
context.Properties.Items.Remove(CookieAuthenticationDefaults.AuthenticationScheme);
// close openid session
context.Properties.Items.Remove(OpenIdConnectDefaults.AuthenticationScheme);
return Task.CompletedTask;
}
}
经过一段时间的调试后,我发现问题出在基础设施本身。当我使用API网关将流量路由到我的lambda时,我缺少POST的路由。只需在aws控制台中api gateway/routes下的/{proxy+}
中添加一个POST路由方法,或者使用类似于以下的地形资源块:
resource "aws_apigatewayv2_route" "get_route" {
api_id = aws_apigatewayv2_api.lambda.id
route_key = "GET /{proxy+}"
target = "integrations/${aws_apigatewayv2_integration.proxy_integration.id}"
}