I'm trying to call the httpget method of a controller.But its always 404.I have added all required directives.When i call the class name directly i get this exception
AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied:
Controller
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace WebApplication2.Controllers
{
[Route("api/[controller]")]
public class ScannerController : Controller
{
[HttpGet]
public async Task<IActionResult> dostuff(string file_id)
{
return null;
}
}
}
Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SpaServices.AngularCli;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using WebApplication2.Models;
namespace WebApplication2
{
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.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
// requires using Microsoft.Extensions.Options
services.Configure<DatabaseSettings>(
Configuration.GetSection(nameof(DatabaseSettings)));
services.AddSingleton<IDatabaseSettings>(sp =>
sp.GetRequiredService<IOptions<DatabaseSettings>>().Value);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
//app.UseSpaStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");
}
});
}
}
}
Change the route on the dostuff method to:
[HttpGet("dostuff")]
Related
I am trying to add a controller with routing to a Razor server-side app. I tried several things but I only see solutions for .NET 6 and cannot figure it out.
I created a controller like this:
using Microsoft.AspNetCore.Mvc;
namespace SAAR.Controllers
{
[ApiController]
[Route("settings/[controller]")]
public class ConfigurationController : ControllerBase
{
public ConfigurationController()
{
}
[HttpGet("test")]
public string Test()
{
return "Test a controller in Razor";
}
}
}
Then in my program.cs I added:
builder.Services.AddControllers();
and
app.UseEndpoints(endpoints => {
endpoints.MapRazorPages();
endpoints.MapControllers();
});
AFAIK this should work and the endpoint http://localhost:5000/settings/test should be there but I get a http 404 error.
What am I doing wrong?
Here my complete program.cs:
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.EntityFrameworkCore;
using SAAR.Areas.Identity;
using SAAR.Data;
using SAAR.Services;
using SAAR.Settings;
using System.Configuration;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
// Add MVC Controllers
builder.Services.AddControllers();
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddTransient<IEmailSender, EmailSender>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
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.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.UseEndpoints(endpoints => {
endpoints.MapRazorPages();
endpoints.MapControllers();
});
app.Run();
Thanks for any help...
In your case,the uri should be http://localhost:5000/settings/Configuration
The name of your controller is Configuration not test
[ApiController]
[Route("settings/[controller]")]
public class ConfigurationController : ControllerBase
{
.....
}
OK, figured it out, thanx!
Just create a new Razor Server project and add a folder 'Controllers' and add a C# class:ConfigurationController.cs:
using Microsoft.AspNetCore.Mvc;
namespace SAAR.Controllers
{
[ApiController]
[Route("[controller]")]
public class ConfigurationController : ControllerBase
{
public ConfigurationController()
{
}
[HttpGet("[action]")]
public string Test()
{
// Route: /Configuration/Test
return "Test a controller in Razor";
}
}
}
In program.cs add this code and remove duplicate app.[Method] calls.
app.UseEndpoints(endpoints => {
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
Insert this in program.cs
builder.Services.AddControllers();
So the complete program.cs looks like:
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.EntityFrameworkCore;
using SAAR.Areas.Identity;
using SAAR.Data;
using SAAR.Services;
using SAAR.Settings;
using System.Configuration;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
// Add MVC Controllers
builder.Services.AddControllers();
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
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.UseEndpoints(endpoints => {
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
app.Run();
You cannot use routing / MVC-controllers in an Razor Server web app.
I am trying to create a controller and my startup.cs is defined like this:
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
namespace ConsoleApp1
{
public class Startup
{
public void ConfigurationServices(IServiceCollection service)
{
service.AddControllersWithViews();
// service.AddControllers(); tried adding this line did not work
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
}
}
However on running the application, I am getting an error:
System.InvalidOperationException: 'Unable to find the required services. Please add all the required services by calling 'IServiceCollection.AddControllers' inside the call to 'ConfigureServices(...)' in the application startup code.'
Please help.
HomeController:
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ConsoleApp1.Controllers
{
public class HomeController : Controller
{
public string Index() // called action methods
{
return "Some string";
}
}
}
Please let me know if any additional details are required
since you are need controller with views, not api one, try this
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
I created a new simple controller But when I enter the following address in the browser, could not find it!
http://localhost:5000/Test/Index
Test.cs:
using Microsoft.AspNetCore.Mvc;
namespace Test.Controllers
{
[Route("[controller]/[action]")]
public class TestController : Controller
{
[HttpGet]
public IActionResult Index()
{
return Content("Welcome");
}
}
}
Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace Test
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddRazorPages().AddRazorRuntimeCompilation();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapRazorPages();
});
}
}
}
Where did I do the wrong thing?
first Edit your Controller attribute :
[Route("[controller]/[action]")]
to
[Route("[controller]")]
and
try this
app.UseEndpoints(endPoints =>
{
endPoints.MapControllerRoute(
"default",
"{controller}/{action}/{id?}");
});
also make sure you are using correct port 5000 or 5001 are defaults
Please check that you are using correct port number.
I am attempting to change my start page in my ASP.NET Core MVC C# app. I want to first take the user to a login page and I have changed in the Startup.cs to this:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Login}/{action=Index}/{id?}");
}
}
and my controller looks like this
public class LoginController : Controller
{
public IActionResult Index()
{
return View();
}
}
And I have a page called Login.cshtml
What am I missing here?
This is my startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using eDrummond.Models;
namespace eDrummond
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<eDrummond_MVCContext>();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(opetions =>
{
options.LoginPath = "/Login/Index";
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseAuthentication();
app.UseCors(
options => options.AllowAnyOrigin()
);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Login}/{action=Index}/{id?}");
});
}
}
}
I am using VS2019 and created an asp.net core app, then selected MVC and all I've done is Scaffold Tables. SO the config should be correct?
You need to take regard of an authentication flow. First you are unauthorized. When you access any page where you aren't authorized you would like to REDIRECT to your login page, right? Then you need to tell this the program:
public void ConfigureServices(IServiceCollection services) {
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
// What kind of authentication you use? Here I just assume cookie authentication.
.AddCookie(options =>
{
options.LoginPath = "/Login/Index";
});
}
public void Configure(IApplicationBuilder app) {
// Add it but BEFORE app.UseEndpoints(..);
app.UseAuthentication();
}
Here is a stackoverflow topic, that addresses your problem:
ASP.NET core, change default redirect for unauthorized
Edit:
It turns out, that you can do something like this:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// You need to comment this out ..
// services.AddRazorPages();
// And need to write this instead:
services.AddMvc().AddRazorPagesOptions(options =>
{
options.Conventions.AddPageRoute("/Login/Index", "");
});
}
2. Edit:
So my first answer was not wrong, but it it did not included the changes to the controller it would need.
There are two solutions:
You add [Authorize] to all controller, you want to be authorized,
for example IndexModel (located in /Pages/Index.cshtml.cs) and when
entered, the program would see, the user is not authorized and would
redirect to /Login/Index (file located in
/Pages/Login/Index.cshtml.cs). Then you don't need to specify a DefaultPolicy or a FallbackPolicy (see source code below for FallbackPolicy reference)
You can make the program say, that all controller need to be
authorized even when not marked by [Authorize]. But then you need to
mark those controller you want pass without authorization with
[AllowAnonymous]. This is how it should be implemented then:
Structure:
/Pages
Index.cshtml
Index.cshtml.cs
/Login
Index.cshtml
Index.cshtml.cs
/Startup.cs
Files:
// File located in /Startup.cs:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.Configuration;
namespace stackoverflow_aspnetcore_59448960
{
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)
{
// Does automatically collect all routes.
services.AddRazorPages();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
// That will point to /Pages/Login.cshtml
options.LoginPath = "/Login/Index";
}); ;
services.AddAuthorization(options =>
{
// This says, that all pages need AUTHORIZATION. But when a controller,
// for example the login controller in Login.cshtml.cs, is tagged with
// [AllowAnonymous] then it is not in need of AUTHORIZATION. :)
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
}
// 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.UseAuthorization();
app.UseEndpoints(endpoints =>
{
// Defines default route behaviour.
endpoints.MapRazorPages();
});
}
}
}
// File located in /Pages/Login/Index.cshtml.cs:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace stackoverflow_aspnetcore_59448960.Pages.Login
{
// Very important
[AllowAnonymous]
// Another fact: The name of this Model, I mean "Index" need to be
// the same as the filename without extensions: Index[Model] == Index[.cshtml.cs]
public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;
public IndexModel(ILogger<IndexModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
// File located in /Pages/Index.cshtml.cs
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace stackoverflow_aspnetcore_59448960.Pages
{
// No [Authorize] needed, because of FallbackPolicy (see Startup.cs)
public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;
public IndexModel(ILogger<IndexModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
You should have folder structure as shown below.
Views
Login
Index.cshtml
It should take you to login page by default.
I'm working on an ASP.NET Core Application and one of my Controllers works fine. But every controller after that does not seem to work, returning 404.
This controller responds as expected:
namespace App.Controllers {
[Route("api/[controller]")]
public class AccountController : CustomControllerBase {...}
}
But this controller, and all others, return 404:
namespace App.Controllers {
[Authorize]
[Route("api/[controller]")]
public class UserController : CustomControllerBase {...}
}
CustomControllerBase looks like this:
namespace App.Controllers {
[ApiController]
public class CustomControllerBase : ControllerBase {
public CustomControllerBase() {
}
}
}
And my Startup.cs looks like this:
namespace App {
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.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddDbContext<DatabaseContext>(options => options.UseMySql(Configuration.GetConnectionString("MySQLConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<DatabaseContext>();
services.AddScoped<IUserService, UserService>();
services.Configure<JWTSettings>(Configuration.GetSection("JWT"));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
} else {
// 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.UseMvc(routes => {
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}"
);
});
app.UseAuthentication();
}
}
}
Any ideas? I've been stuck on this for a few days and I cannot figure out what I am doing wrong.
Thanks