我正在启动一个 ASP.NET Core 项目,我想知道在 MacOS 上与 Windows 上使用 ASP.NET Core 进行开发是否有任何缺点,如果有的话,它们是什么?
我按照https://learn.microsoft.com/en-us/aspnet/core/blazor/components/css-isolation?view=aspnetcore-8.0#additional-resources中的教程进行操作
现在 CSS 隔离效果很好。
我有一个问题,CSS 隔离样式(就像这个打击)没有缩小。
<link href="{ASSEMBLY NAME}.styles.css" rel="stylesheet">
我考虑过使用像 BuildBundlerMinifier 这样的工具来最小化它。但是,它似乎不是静态文件,而是动态生成的,因此我无法使用第三方工具来最小化它。
有什么方法可以最小化它以使页面访问更快吗?
谢谢。
我正在将 ASP.NET Core Razor Pages 与 Identity 结合使用。我以标准方式使用StatusCodePages 中间件:
app.UseStatusCodePagesWithReExecute("/Error", "?statusCode={0}");
在该 razor 页面中,我可以打开状态代码以呈现 401、403、404 和“其他”(400..599 范围内的所有其他代码)的不同内容。然而这会变得混乱;我更喜欢单独的页面。
所以代替这个:
- /Pages/Error.cshtml
我要这个:
- /Pages/401.cshtml
- /Pages/403.cshtml
- /Pages/404.cshtml
- /Pages/400_599.cshtml
那可能吗?
我已经知道的丑陋的解决方法:
- 我可以使用 URL 模板
"/Error/{0}"
,但这不切实际:我必须为 400..599 范围内的每个代码定义一个单独的页面。我绝对不能这样做。 - 在“/Pages/Error.cshtml.cs”页面模型类中,我可以根据状态代码重定向到不同的页面。我不想这样做,我怀疑这对搜索引擎优化不利。
- 对于“/Error”端点,我可以使用带有视图的 MVC 控制器(而不是 Razor Pages);操作方法可以返回适当的视图。不错的解决方案,但增加了不必要的复杂性;我更喜欢 Razor Pages 方法。
我有一个带有请求本地化的 Net8 Web 应用程序。当抛出错误时,它无法导航到错误页面,因为它将 URL 中的错误视为文化并尝试导航到http://localhost:5245/Error/Index
.
如果我指定app.UseExceptionHandler("/en/Error")
它是成功的,但我无法以另一种语言提供该页面。
我在编写自定义错误处理程序方面取得了一些成功,但我想将用户重定向到错误页面,因为包含页面导航,而不是返回纯文本或手动编码 HTML。
程序.cs
using System.Globalization;
using LocalizationWithErrors.Conventions;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Localization.Routing;
using Microsoft.Extensions.Options;
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[]
{
new CultureInfo("en"),
new CultureInfo("fr"),
};
options.DefaultRequestCulture = new RequestCulture(supportedCultures[0]);
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
options.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider() { Options = options });
});
services.AddRazorPages(options =>
{
options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());
});
var app = builder.Build();
/*
It works if I include the language in the path to the
ExceptionHandler page, but I'm not able to add the path for multiple supported languages
*/
// app.UseExceptionHandler("/en/Error");
app.UseExceptionHandler("/Error");
var localizationOptions = app.Services.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value;
app.UseRouting();
app.UseStaticFiles();
app.UseRequestLocalization(localizationOptions);
app.MapRazorPages();
app.Run();
RouteModelConvention:这将为应用程序中的所有页面创建每个支持区域性的路由模型约定。
en/Index
,,,,,,,fr/index
en/Privacy
fr/Privacy
en/Error
fr/Error
我尝试在约定中排除/包括错误页面,以查看它如何影响路由,但它没有看到任何效果。
GlobalTemplatePageRouteModelConvention.cs
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace LocalizationWithErrors.Conventions;
public class GlobalTemplatePageRouteModelConvention : IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
var selectorCount = model.Selectors.Count();
if (!model.RelativePath.Contains("Error"))
{
for (int i = 0; i < selectorCount; i++)
{
SelectorModel selector = model.Selectors[i];
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Order = -1,
Template = AttributeRouteModel.CombineTemplates("{culture}",
selector.AttributeRouteModel!.Template
),
}
});
}
}
}
}
页面/Index.cshtml
@page
@using System.Globalization
@using Microsoft.AspNetCore.Localization
@model IndexModel
@{
ViewData["Title"] = "Home page";
var requestCultureFeature = HttpContext.Features.Get<IRequestCultureFeature>();
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>CultureInfo: @requestCultureFeature.RequestCulture.Culture</p>
<p>CurrentUICulture: @requestCultureFeature.RequestCulture.UICulture</p>
</div>
<form method="POST">
<button type="submit">Cause an error</button>
</form>
页面/Index.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace LocalizationWithErrors.Pages;
public class IndexModel : PageModel
{
/* Throw an exception to trigger the Error handler */
public async Task<IActionResult> OnPost() => throw new FileNotFoundException("Whoops");
}
页面/Error.cshtml
@page
@model ErrorModel
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
页面/Error.cshtml.cs
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace LocalizationWithErrors.Pages;
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
public void OnGet() => RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
}
如何将文化包含在错误页面的路由中?
编辑 2024-04-09 22:40 (-5:00 GMT) 根据 @ Guru Stron的请求,我编辑了该帖子以包含重新创建问题所需的所有代码。
这是身份验证方案:
services.AddAuthentication(option =>
{
option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
option.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidIssuer = Configuration["JWT:ValidAudience"],
ValidAudience = Configuration["JWT:ValidIssuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:Secret"]))
};
});
这是我的管道:
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(); //custom
app.UseAuthentication(); //CUSTOM
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
如果我删除Authorize
控制器顶部的属性,则请求会成功发送,但如果添加它则不起作用。
[Route("api/[controller]")]
[ApiController]
[Authorize]//(Roles = UserRoles.Admin)]
public class ValuesController : ControllerBase
{
// GET: api/<ValuesController>
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
如果我删除该Authorize
属性,此代码将起作用。即使没有任何角色,它也不起作用。
这是我的appSettings.json
:
"JWT": {
"ValidAudience": "User",
"ValidIssuer": "https://localhost:44336",
"Secret": "ThisIsMySecretKEYadadasdasd939239" // MUST BE 16 CHARACTERS
}
这是登录代码:
public async Task<TokenModel> SignIn(SignInModel model)
{
var user = await _context.FindByNameAsync(model.UserName);
if (user != null && await _context.CheckPasswordAsync(user, model.Password)) //Rocko@135
{
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var userRoles = await _context.GetRolesAsync(user);
foreach (var userRole in userRoles)
{
authClaims.Add(new Claim(ClaimTypes.Role, userRole));
}
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Secret"]));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: _configuration["JWT:ValidIssuer"],
audience: _configuration["JWT:ValidAudience"],
expires: DateTime.Now.AddDays(2),
claims: authClaims,
signingCredentials: credentials);
return new TokenModel
{
Token = new JwtSecurityTokenHandler().WriteToken(token),
Expiration = token.ValidTo,
Username = user.UserName
};
}
else
{
return new TokenModel
{
Token = null,
Expiration = null,
Username = string.Empty
};
}
}
这是我的智威汤逊
https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiUm9ja28iLCJqdGkiOiI0NTQ2MjhkMy1jMGM1LTQ1MTUtODQ0My1kMDQ4Y2ZhNzM1NWYiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJBZG1pbiIsImV4cCI6MTcxMTA1NDkzNSwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzMzYiLCJhdWQiOiJVc2VyIn0.FQBlJENwQWzuvQ1NwzRBaTuk7I3h2YBPxhWo1vT7PUw
OnChange 在 balzor Web 程序集中的 InputFile 标记中不起作用。当我上传文件时,LoadFiles 没有被调用。InputFileChangeEventArgs 不起作用,上传文件时未命中断点。我已经使用 blazor web 应用程序来创建它,并想要上传一个 excel,然后将数据显示到页面中。
@page "/weather"
@attribute [StreamRendering]
@using System
@using System.IO
@using Microsoft.AspNetCore.Hosting
@inject IWebHostEnvironment Environment
<PageTitle>File Upload 1</PageTitle>
<h1>File Upload Example 1</h1>
<p>
<label>
Max file size:
<input type="number" @bind="maxFileSize" />
</label>
</p>
<p>
<label>
Max allowed files:
<input type="number" @bind="maxAllowedFiles" />
</label>
</p>
<p>
<label>
Upload up to @maxAllowedFiles of up to @maxFileSize bytes:
<InputFile OnChange="LoadFiles" multiple />
</label>
</p>
@if (isLoading)
{
<p>Uploading...</p>
}
else
{
<ul>
@foreach (var file in loadedFiles)
{
<li>
<ul>
<li>Name: @file.Name</li>
<li>Last modified: @file.LastModified.ToString()</li>
<li>Size (bytes): @file.Size</li>
<li>Content type: @file.ContentType</li>
</ul>
</li>
}
</ul>
}
@code {
private List<IBrowserFile> loadedFiles = new();
private long maxFileSize = 1024 * 15;
private int maxAllowedFiles = 3;
private bool isLoading;
private async Task LoadFiles(InputFileChangeEventArgs e)
{
isLoading = true;
loadedFiles.Clear();
foreach (var file in e.GetMultipleFiles(maxAllowedFiles))
{
try
{
var trustedFileName = Path.GetRandomFileName();
var path = Path.Combine(Environment.ContentRootPath,
Environment.EnvironmentName, "unsafe_uploads",
trustedFileName);
await using FileStream fs = new(path, FileMode.Create);
await file.OpenReadStream(maxFileSize).CopyToAsync(fs);
loadedFiles.Add(file);
}
catch (Exception ex)
{
}
}
isLoading = false;
}
}
谢谢你帮助我。抱歉描述太长...我尝试详细说明
这是我的ProcessController
:
namespace MVCDemo.Controllers
{
public class ProcessController : Controller
{
// GET Process
public ViewResult List()
{
var processList = from p in Process.GetProcesses()
select p;
ViewData.Model = processList.ToList();
return View();
}
// GET Process/Details/5
public ActionResult Details(int id)
{
var process = (from p in Process.GetProcesses()
where p.Id == id
select p).Single();
return View(process);
}
}
}
这是我的Details.cshtml
观点:
@this.Model.ProcessName <br />
@this.Model.Id
这是我的List.cshtml
观点:
<div>
<h1>List</h1>
<ul>
@foreach (var process in this.Model)
{
<li>
@Html.ActionLink("process.ProcessName", "Details", new { id = process.Id })
</li>
}
</ul>
</div>
我的问题是,每一行我只能看到“process.ProcessName”,而不是列表,如果我的看起来List.cshtml
像这样:
<div>
<h1>List</h1>
<ul>
@foreach (var process in this.Model)
{
<li>
@process.ProcessName
</li>
}
</ul>
</div>
我可以看到问题可能出在这一行
@Html.ActionLink("process.ProcessName", "Details", new { id = process.Id })
但我不知道如何更改process.ProcessName
以获取列表,然后我可以单击。如果我这样改变它就行不通。那么整条线就不跑了。
<div>
<h1>List</h1>
<ul>
@foreach (var process in this.Model)
{
<li>
@Html.ActionLink(@process.ProcessName, "Details", new { id = process.Id })
</li>
}
</ul>
</div>
我一直在尝试将以字节数组形式存储在数据库中的文件转换为网站上的可下载文件。下载链接似乎会产生一行重复的乱码。
我的文档已作为此类存储在数据库中
public class User
{
public string ResumeName { get; set; }
public byte[] Resume { get; set; }
public string ResumeContentType { get; set; }
}
为了将信息作为文档检索回来,我使用这个函数
public IActionResult Download(byte[] filebytes, string type, string name)
{
return File(filebytes, type, name);
}
网页本身使用此操作链接来生成创建下载链接的按钮
@Html.ActionLink("Download File", "Download", new {
filebytes = @UserManager.GetUserAsync(User).Result.Resume,
type = @UserManager.GetUserAsync(User).Result.ResumeContentType,
name = @UserManager.GetUserAsync(User).Result.ResumeName
})
运行代码时,单击链接不会执行任何可见操作,这意味着我无法看到它是如何出错的。然而,在新选项卡中打开链接会产生这个已大大缩短的长链接
https://localhost:7095/Home/Download?filebytes=80&filebytes=75&......(this repeated several hundred times)...... filebytes=0&filebytes=0&filebytes=0&filebytes=0&type=application%2Fvnd.openxmlformatsofficedocument.wordprocessingml.document&name=__xid-43512761_1.docx
为什么会发生这种情况?有办法解决吗?
我创建了一个 ASP.NET Core Web API 应用程序来访问 SQL 数据库。
然后,我使用脚手架生成 3 个表(TB1、TB2、TB3)和 DbContext 的模型。
TB1
model 包含其所有属性,但还包含一个LIST<>
forTB2
类,如下所示:
public virtual ICollection<TB2> TB2s { get; set; } = new List<TB2>();
TB2
model 包含其所有属性,但还包含一个LIST<>
forTB3
类,如下所示:
public virtual ICollection<TB3> TB3s { get; set; } = new List <TB3>();
在控制器中,我包含了 TB2
[HttpGet]
public async Task<IEnumerable<Patient>> Get() => await _context.TB1s.Include(c => c.TB2s).ToListAsync();
这有效!
但模型仍然返回空TB3s : [ ]
所以我将以下代码添加到 TB1 类中
public virtual ICollection<TB3> TB3s { get; set; } = new List<TB3>();
现在我可以尝试将其包含在控制器方法中:
[HttpGet]
public async Task<IEnumerable<Patient>> Get() => await _context.TB1s.Include(c => c.TB2s).Include(p => p.TB3s).ToListAsync();
但它仍然不起作用。任何帮助是极大的赞赏。
我有一个 .net 8 razor 页面应用程序,我使用以下代码添加了来自数据库的页面路由:
options.Conventions.AddPageRoute(route.FullName, route.Key.ToString());
例如,我为页面/帐户/登录添加了页面路由/A64592D0-05AD-4E0D-8A0C-5E5259800A19。现在我想避免有人可以直接使用/Account/Login 访问该页面。
背景:每个页面都可以通过导航树中的多个路径访问,这样就可以评估用户当前在树上的位置,并根据位置和用户处理不同的权限。
我只是可以将 @page 指令设置为一些未使用的值,但这并不能避免使用该值访问页面的可能性。
如何删除或禁用所有页面的默认页面路由?