Тема. На localhost с vsstudio 2019 работает нормально. Но на рабочем сервере метод PUT EditPost возвращает сообщение «Ошибка 404 не найдена». Но таблица редактирования devextreme тем же методом отлично работает на том же сервере. Я потратил много времени. Добавлена анти-подделка. Перемещено на URL.Actions. Изменен контроллер mvc на api. Добавлены маршруты. Добавлены параметры. Ничего не помогло Запросы такие же, как у jquery ajax и devexreme. Но devexreme работает, а ajax - нет.
Пожалуйста, помогите!
asp. net mvc core v 3.1 apache2 последняя версия Ubuntu с использованием certbot ssl.
<VirtualHost *:*>
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>
<VirtualHost *:80>
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:10003/
ProxyPassReverse / http://127.0.0.1:10003/
ProxyPass /ws wss://127.0.0.1:10003/
ProxyPassReverse /ws wss://127.0.0.1:10003/
ServerName server.postidea.ru
ServerAlias *.server.postidea.ru
ErrorLog ${APACHE_LOG_DIR}server.postidea-error.log
CustomLog ${APACHE_LOG_DIR}server.postidea-access.log common
RewriteEngine on
RewriteCond %{SERVER_NAME} =server.postidea.ru [OR]
RewriteCond %{SERVER_NAME} =*.server.postidea.ru
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
RewriteRule ^ wss://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
index. chtml:
function savePost() {
var data = {};
data.key = postIndexes[currentIndex];
var lookup = $("#theme").data("dxLookup");
var selectedValue = parseInt(lookup.option("value"));
if (!isNaN(selectedValue)) {
data.values =
"{\"Title\":\"" +
$("#title").val() +
"\", \"Text\":\"" +
$("textarea").text() +
"\", \"ThemeId\":" +
selectedValue +
"}";
$.ajax({
url: '@Url.Action("EditPost", "Api")',
type: 'PUT',
beforeSend: function(xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
data: data,
success: function() {
new window.Noty({
text: "Saved",
type: 'success'
}).show();
},
error: function() {
new window.Noty({
text: "Error",
type: 'error'
}).show();
}
});
} else {
new window.Noty({
text: "Выберете тему и сохраните пост.",
type: 'warning'
}).show();
}
updateCounters();
}
<button type="button" id="saveButton" onclick="savePost()" class="btn btn-success m-1"><i class="fas fa-save"></i></button>
Запуск:
public class Startup
{
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
Configuration = configuration;
WebHostEnvironment = env;
}
private IWebHostEnvironment WebHostEnvironment { get; }
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
var configuration = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json")
.Build();
services.AddEntityFrameworkSqlite().AddDbContext<ApplicationDbContext>();
services.AddLogging(config =>
{
// clear out default configuration
config.ClearProviders();
config.AddConfiguration(Configuration.GetSection("Logging"));
config.AddDebug();
config.AddEventSourceLogger();
config.AddConsole();
});
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
{
options.LoginPath = "/Home/Authorization";
options.LogoutPath = "/Home/Logout";
});
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
services.AddHttpContextAccessor();
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
services.AddSingleton<IEasyBotParser, EasyBotParser>();
services.AddSingleton<IEpicStarsParser, EpicStarsParser>();
services.AddSingleton<IHostedService, InstagramParser>();
if (WebHostEnvironment.IsDevelopment())
{
services.AddLiveReload();
}
// Add framework services.
services.AddControllersWithViews().AddNewtonsoftJson(options =>
options.SerializerSettings.ContractResolver = new DefaultContractResolver());
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
using (var db = new ApplicationDbContext(Server.DatabasePath))
{
db.Database.Migrate();
}
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
app.UseLiveReload();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors();
app.UseForwardedHeaders();
var cookiePolicyOptions = new CookiePolicyOptions
{
MinimumSameSitePolicy = SameSiteMode.Lax,
};
app.UseCookiePolicy(cookiePolicyOptions);
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
}
Контроллер:
[Route("/api/v1/")]
[ApiController]
public class ApiController : Controller
{
[Route("EditPost")]
[HttpPut]
public async Task<IActionResult> EditPost([FromForm]string key, [FromForm]string values)
{
await using (var db = new ApplicationDbContext(Server.DatabasePath))
{
var post = db.Posts.First(a => a.Id == int.Parse(key));
JsonConvert.PopulateObject(values, post);
if (!TryValidateModel(post))
return BadRequest();
await db.SaveChangesAsync();
}
return Ok();
}
}
Параметры Данные формы:
key: 4
values: {"Title":"text", "ThemeId":2}
Запрос из индекса. chtml с ajax:
PUT /api/v1/EditPost HTTP/1.1
Host: server.postidea.ru
Connection: keep-alive
Content-Length: 10069
Accept: text/plain, */*; q=0.01
Sec-Fetch-Dest: empty
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: https://server.postidea.ru
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Referer: https://server.postidea.ru/Home/Posts
Accept-Encoding: gzip, deflate, br
Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7,ky;q=0.6,th;q=0.5
Cookie: .AspNetCore.Antiforgery.13N0FYOFCVQ=CfDJ8LY3qlvdi1RHk_ITf7otcTdrAkN7ku0AWcyM5PjADg1iTiMzmdkiS-PxK17TfZGX7A55OSEdj71ud8IIjyr05v745MEuq3jvwZA4dwQP4GbBym_xFy3Ho_n3Hgk79HX09e0uu7c_HzDsxHp7O47iJFc; RequestVerificationToken=CfDJ8LY3qlvdi1RHk_ITf7otcTe7lhEFS2P_2mCq29qWzYuibrFGH65qh9uZPaiK-8JL0sPpKz4U32nqrIlXop2zSyaORMqvWJVTX3LxHrIGcBBu_r2azG2QT2K4m0iVPPb5kH-1f0XnFdVs1zyrQvwvcQg; .AspNetCore.Cookies=CfDJ8LY3qlvdi1RHk_ITf7otcTcHUDwyarRK9XApk6c920dqfk-5k9ODZ0Rnd86Aafu-cNk3UNSw4RX1g-PBkb2pbmx23-3_f2Pyij48o-ovYusWGEMeqR8R1oK-q0de_6Dl4z9K19G1S-_-K17SzQKYWcoVwnmJFAuERX31k49NfNLiG_of-3nDFH4XUfXwwlU1ahJdpMaZOMHgsIwqqMg4V8IzPLEVWVkk7MD2J4CGy8_fZLUcEk0DJ-zREdZrtBplup5SQPMBT3e5kl6Ys0w9IsCsi15Ny2R2Kdi742tzOePJrEli68O48y0_hQFqqSAx4vWH7gwpfuqt5kewLKvt9ioe0FRn1-60wBkfEP5WuwSrHw7ksi245YKyiXVPXcKK2w
Запрос от devextreme:
PUT /api/v1/EditPost HTTP/1.1
Host: server.postidea.ru
Connection: keep-alive
Content-Length: 5197
Accept: */*
Sec-Fetch-Dest: empty
X-Requested-With: XMLHttpRequest
XSRF-TOKEN: CfDJ8LY3qlvdi1RHk_ITf7otcTcx5u4zjQzgxyR_cNZ5oonQ1JxDywbp9hxWiWgIZEQyxX2yjULA00iDNTOs7LrC4lQ-0mz2n4MJoHNUOuZZFOvvuwj7RKXKdUI2rJKzIKn7_6jIj4P9JBSFuaIrlQrOO7YLLg7gl-B3UWsqYnIjzpnuG73BhThGTPwuHFGP1Pjn-Q
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: https://server.postidea.ru
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Referer: https://server.postidea.ru/
Accept-Encoding: gzip, deflate, br
Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7,ky;q=0.6,th;q=0.5
Cookie: .AspNetCore.Antiforgery.13N0FYOFCVQ=CfDJ8LY3qlvdi1RHk_ITf7otcTdrAkN7ku0AWcyM5PjADg1iTiMzmdkiS-PxK17TfZGX7A55OSEdj71ud8IIjyr05v745MEuq3jvwZA4dwQP4GbBym_xFy3Ho_n3Hgk79HX09e0uu7c_HzDsxHp7O47iJFc; RequestVerificationToken=CfDJ8LY3qlvdi1RHk_ITf7otcTe7lhEFS2P_2mCq29qWzYuibrFGH65qh9uZPaiK-8JL0sPpKz4U32nqrIlXop2zSyaORMqvWJVTX3LxHrIGcBBu_r2azG2QT2K4m0iVPPb5kH-1f0XnFdVs1zyrQvwvcQg; .AspNetCore.Cookies=CfDJ8LY3qlvdi1RHk_ITf7otcTcHUDwyarRK9XApk6c920dqfk-5k9ODZ0Rnd86Aafu-cNk3UNSw4RX1g-PBkb2pbmx23-3_f2Pyij48o-ovYusWGEMeqR8R1oK-q0de_6Dl4z9K19G1S-_-K17SzQKYWcoVwnmJFAuERX31k49NfNLiG_of-3nDFH4XUfXwwlU1ahJdpMaZOMHgsIwqqMg4V8IzPLEVWVkk7MD2J4CGy8_fZLUcEk0DJ-zREdZrtBplup5SQPMBT3e5kl6Ys0w9IsCsi15Ny2R2Kdi742tzOePJrEli68O48y0_hQFqqSAx4vWH7gwpfuqt5kewLKvt9ioe0FRn1-60wBkfEP5WuwSrHw7ksi245YKyiXVPXcKK2w