I have created the web API for countries and try to access it from angular 7, the GET details and GET record by id is working fine where as DELETE method not working.
When i try to access DELETE there is no call send to web API from angular 7.
// DELETE: api/Country/5
[HttpDelete("{id}")]
public IActionResult Delete(long id) {
Country country = _dataRepository.Get(id);
if (country == null) {
return NotFound("The Employee record couldn't be found.");
}
_dataRepository.Delete(country);
return NoContent();
}
// GET: api/Countries
[HttpGet]
public IActionResult Get() {
IEnumerable < Country > country = _dataRepository.GetAll();
return Ok(country);
}
// GET: api/Country/5
[HttpGet("{id}", Name = "Get")]
public IActionResult Get(long id) {
Country country = _dataRepository.Get(id);
if (country == null) {
return NotFound("The Employee record couldn't be found.");
}
return Ok(country);
}
export class CountriesComponent {
public countries: Country[];
bUrl = 'https://localhost:44324/';
constructor(private http: HttpClient, private router: Router) {
this.http.get<Country[]>(this.bUrl + 'api/country').subscribe(result => {
this.countries = result;
}, error => console.error(error));
}
btnClick = function (id) {
this.router.navigateByUrl('/country-edit/' + id);
};
btnDelete = function (id) {
return this.http.delete(this.bUrl + 'api/Country/' + id);
// return this.http.get<Country[]>(this.bUrl + 'api/country/'+ id).subscribe(result => {
// this.countries = result;
// }, error => console.error(error));
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
services.AddDbContext<DataBaseContext>(opts => opts.UseSqlServer("server=.; database=FoodFactory; Integrated Security=SSPI"));
services.AddScoped<IDataRepository<Country>, CountryManager>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseCors(x => x.AllowAnyMethod());
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 =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
Try check your web API webconfig, there might be missing verb DELETE.
Try to add the verb DELETE, example as below:
add name="ExtensionlessUrl-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,DELETE" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
Hope this helps.
Updated (For .NET Core)
Step 1: Register CORS services
Call AddCors in Startup.ConfigureServices to add CORS services to the app's service container:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
}
Step 2: Enable CORS with CORS Middleware
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
);
}
Try if this works for you.
Related
I created asp.net core with React template in VS 2019, i need to authorize a controller method so I first registered my app on Azure AD and than i used this Startup.cs configurations:
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.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
services.AddControllersWithViews().AddMicrosoftIdentityUI();
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/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.UseSpaStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
}
}
In the controller I used AuthorizeForScopes and ITokenAcquisition as follows
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly ITokenAcquisition tokenAcquisition;
public WeatherForecastController(ITokenAcquisition tokenAcquisition)
{
this.tokenAcquisition = tokenAcquisition;
}
[AuthorizeForScopes(Scopes = new[] { "https://tenantname.sharepoint.com/AllSites.FullControl" })]
[HttpGet]
public async Task<IEnumerable<WeatherForecast>> Get()
{
string accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(new[] { "https://tenantname.sharepoint.com/AllSites.FullControl" });
......
......
}
}
but when i try to fetch the data i have a CORS error
Can you help me
Regarding the issue, please refer to the following steps
Register client application and server application
Use React project template with ASP.NET Core
Client application
a. Install msal
npm install msal
b. Define MsalAuthProvider.
import React, { Component } from 'react';
import { UserAgentApplication } from 'msal';
const msalConfig = {
authority: 'https://login.microsoftonline.com/common',
clientId: '232a1406-b27b-4667-b8c2-3a865c42b79c',
redirectUri: document.getElementById('root').baseURI
};
export const msalAuth = new UserAgentApplication({
auth: msalConfig
});
export function withAuth(HocComponent) {
return class extends Component {
constructor(props) {
super(props);
this.state = {
isAuthenticated: false,
user: {},
renewIframe: false,
hasError: false,
errorMessage: null
};
}
async componentWillMount() {
msalAuth.handleRedirectCallback(() => {
let userAccount = msalAuth.getAccount();
this.setState({
isAuthenticated: true,
user: userAccount
});
}, (authErr, accountState) => { // on fail
console.log(authErr);
this.setState({
hasError: true,
errorMessage: authErr.errorMessage
});
});
if (msalAuth.isCallback(window.location.hash)) {
this.setState({
auth: {
renewIframe: true
}
});
return;
}
let userAccount = msalAuth.getAccount();
if (!userAccount) {
msalAuth.loginRedirect({});
return;
} else {
this.setState({
isAuthenticated: true,
user: userAccount
});
}
}
onSignIn() {
msalAuth.loginRedirect({});
}
onSignOut() {
msalAuth.logout();
}
render() {
if (this.state.renewIframe) {
return <div>hidden renew iframe - not visible</div>;
}
if (this.state.isAuthenticated) {
return <HocComponent auth={this.state} onSignIn={() => this.onSignIn()} onSignOut={() => this.onSignOut()} {...this.props} />;
}
if (this.state.hasError) {
return <div>{this.state.errorMessage}</div>;
}
return <div>Login in progress...</div>;
}
};
}
c. Update App.js
import { withAuth } from './msal/MsalAuthProvider';
import './custom.css'
class RootApp extends Component {
static displayName ="Azure AD application";
render () {
return (
<Layout>
...
</Layout>
);
}
}
//enable auth when we access the page
const App = withAuth(RootApp)
export default App;
call the API
import { msalAuth } from '../msal/MsalAuthProvider'
async componentDidMount() {
// get token and call the api
try {
const accessTokenRequest = {
scopes: ["api://872ebcec-c24a-4399-835a-201cdaf7d68b/access_as_user"]
}
var authRes
var accessToken = null;
try {
authRes = await msalAuth.acquireTokenSilent(accessTokenRequest);
accessToken=authRes.accessToken
}
catch (error) {
console.log("AquireTokenSilent failure");
authRes = await msalAuth.acquireTokenPopup(accessTokenRequest);
accessToken = authRes.accessToken
}
console.log(accessToken)
this.populateWeatherData(accessToken);
}
catch (err) {
var error = {};
if (typeof (err) === 'string') {
var errParts = err.split('|');
error = errParts.length > 1 ?
{ message: errParts[1], debug: errParts[0] } :
{ message: err };
} else {
error = {
message: err.message,
debug: JSON.stringify(err)
};
}
this.setState({
user: {},
isLoading: false,
error: error
});
}
}
async populateWeatherData(token) {
const response = await fetch('weatherforecast', {
method: 'get',
headers: new Headers({
'Authorization': 'Bearer ' + token
})
});
const data = await response.json();
this.setState({ forecasts: data, loading: false });
}
Server code
a. Startup.cs
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.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
services.AddControllersWithViews();
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/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.UseSpaStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
}
}
b. Controller
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly ITokenAcquisition tokenAcquisition;
public WeatherForecastController(ITokenAcquisition tokenAcquisition)
{
this.tokenAcquisition = tokenAcquisition;
}
[AuthorizeForScopes(Scopes = new[] { "<your scope>" })]
[HttpGet]
public async Task<IEnumerable<WeatherForecast>> Get()
{
string accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(new[] { "<your scope>" });
......
......
}
}
For more details, please refer to here snd here.
I need to open both web pages and API in a single project. But I have difficulty with the route. I am not able to independently set route requests with mapwhen. First route; I route all language dependent requests to a single controller. This is for my web pages. The second is the default api route.
This My middlewareExtension
public static class WebBuilderMiddlewaresExtension
{
public static IApplicationBuilder UseWebBuilderMiddlewares(this IApplicationBuilder builder)
{
builder.MapWhen(context => context.Request.Path.StartsWithSegments("/api"), appBuilder =>
{
builder.UseRouting();
builder.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action}/{id?}");
});
});
builder.MapWhen(context => context.Request.RouteValues["culture"] != null || string.IsNullOrEmpty(context.Request.Path), appBuilder =>
{
builder.UseRouting();
builder.UseMiddleware<LanguageMiddleware>();
builder.UseMiddleware<RouteMiddleware>();
builder.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "culture-route",
pattern: "{culture=tr-TR}/{*default}",
defaults: new { culture = "tr-TR", controller = "Home", action = "Index" }
);
});
});
return builder;
}
This is my startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
using (var client = new WebBuilderContext())
{
client.Database.EnsureCreated();
}
}
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.AddLocalization(opts => opts.ResourcesPath = "Resources");
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("tr-TR"),
new CultureInfo("en-US"),
};
// Dil ayarlarını ve varsayılan dil seçimini tanımlıyoruz.
var localizationOptions = new RequestLocalizationOptions
{
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures,
DefaultRequestCulture = new RequestCulture("tr-TR"),
};
var requestProvider = new RouteDataRequestCultureProvider();
localizationOptions.RequestCultureProviders.Insert(0, requestProvider);
services.AddScoped<UiDataService>();
services.AddDbContext<WebBuilderContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DeveloperMsSql")));
services.AddSession(options => {
options.Cookie.Name = "Language";
options.IdleTimeout = TimeSpan.FromMinutes(30); // Zamanı ayarlayabilirsiniz
});
}
// 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("/Home/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.UseSession();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseWebBuilderMiddlewares();
For api route in .net core,you need to use Route Attribute.
Here is a sample(I add an api to .net core mvc):
[ApiController]
[Route("api/[controller]")]
public class ApiController : ControllerBase
{
[HttpGet]
[Route("Get")]
public async Task<IActionResult> Get()
{
return Ok();
}
}
result:
and change mvc route,you can change it in startup.cs:
Configure:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
It's the first time I'm asking a question.
I want to build a graphQL server by using ASP.NET Core project.
I use this line by line, but in the end, it does not show the schema. I tried every thing that i could. The intresting is that the server works. the only thing is that does not show the schema.
here are some codes that I'm using.
Schema:
public class RootSchema : Schema, ISchema
{
public RootSchema(IDependencyResolver resolver) : base(resolver)
{
Query = resolver.Resolve<RootQuery>();
}
}
Query:
public class RootQuery : ObjectGraphType
{
public RootQuery()
{
Field<AuthorType>(
name: "authors", resolve: context =>
{
return new Author()
{
FirstName = "Jane"
};
});
}
}
The Controller:
[Route("graphql")]
public class GraphQLController : Controller
{
private readonly ISchema _schema;
private readonly IDocumentExecuter _executer;
private readonly IDependencyResolver _resolver;
public GraphQLController(ISchema schema, IDocumentExecuter executer, IDependencyResolver resolver)
{
_schema = schema;
_executer = executer;
_resolver = resolver;
}
[HttpGet(nameof(Test))]
public IActionResult Test()
{
return Ok("Salam");
}
[HttpPost]
public async Task<IActionResult> Post([FromBody] GraphQLQuery query)
{
var result = await _executer.ExecuteAsync(_ =>
{
_.Schema = _schema;
_.Query = query.Query;
_.Inputs = query.Variables?.ToInputs();
}).ConfigureAwait(false);
if (result.Errors?.Count > 0)
{
return Problem(detail: result.Errors.Select(_ => _.Message).FirstOrDefault(), statusCode: 500);
}
return Ok(result.Data);
}
}
The Configure function at the sturtup:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/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.UseStaticFiles();
app.UseGraphiQl("/graphql");
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
The ConfigureServices function at the Sturtup:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IDependencyResolver>(_ => new
FuncDependencyResolver(_.GetRequiredService));
services.AddScoped<IDocumentExecuter, DocumentExecuter>();
services.AddScoped<IDocumentWriter, DocumentWriter>();
services.AddScoped<RootQuery>();
services.AddScoped<AuthorType>();
services.AddScoped<BlogPostType>();
services.AddScoped<ISchema, RootSchema>();
services.AddControllers();
services.AddControllersWithViews();
}
any help would be appreciated.
I have a very strange issue.
Suddenly, when I start debugging on my project, I am redirected to Home/Error instead of Home/Index
without any apparent error or message.
The application is very simple because I just created it today.
This is my startup:
public Startup(IConfiguration configuration)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.SystemDefault;
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.AddSingleton<IConfiguration>(Configuration);
services.Configure<GzipCompressionProviderOptions>(options => options.Level = CompressionLevel.Optimal);
services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
options.Providers.Add<GzipCompressionProvider>();
});
// Without AddNewtonsoftJson actions that receive JSON Objects Body will return error 406
services.AddControllersWithViews().AddNewtonsoftJson();
services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(60);
});
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddHttpContextAccessor();
services.AddTransient<IElasticsearchService, ElasticsearchService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/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();
// Enable compression (must be before UseStaticFiles)
app.UseResponseCompression();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
And this is (the only one for now) my controller:
public HomeController(ILogger<HomeController> logger, IHttpContextAccessor httpContextAccessor, IElasticsearchService elasticsearchService)
: base (logger, httpContextAccessor, elasticsearchService) { }
public async Task<IActionResult> Index(Dictionary<string, string> #params)
{
// some code
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
string errorMessage = string.Empty;
if (TempData["ErrorMessage"] != null)
{
errorMessage = TempData["ErrorMessage"].ToString();
TempData["ErrorMessage"] = null;
}
ViewBag.ErrorMessage = errorMessage;
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
I think I solved the problem on my own, maybe the issue was, that I used a RedirectToPermanent() on my Index and from then on, it always redirect me on Error.
I cleaned the cache and the temporary files and now it seems to work.
i am setting up a new application and wants to store the complaint of a customer by using session. For Session i use email as session ID
I am using database SQL, ASP MVC version 2.1, also using this service in startup file "services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);"
Startup fileenter code here
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.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-
essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSingleton<ICustomerRepository, CustomerRepository>();
services.AddSingleton<IComplaintRepository, ComplaintRepository>();
services.AddSingleton<IAdminRepository, AdminRepository>();
services.AddDistributedMemoryCache();
services.AddSession();
services.AddMvc();
}
// 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("/Home/Error");
app.UseHsts();
}
app.UseMvcWithDefaultRoute();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseSession();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
Controller file having Signup functionenter code here
public IActionResult Signup()
{
if (HttpContext.Session.GetString("email") != null)
{
return RedirectToAction(nameof(Index));
}
else
{
return View();
}
}
[HttpPost]
public IActionResult Signup([Bind("CustomerEmail", "CustomerName", "CustomerContact", "CustomerAddress", "CustomerPassword", "ConfirmPassword")] Customer customer)
{
if (customer.ConfirmPassword != customer.CustomerPassword)
{
ViewBag.Error = "Your password and confirm password doesn't match";
return View();
}
if (_customer.EmailExist(customer.CustomerEmail))
{
ViewBag.Error = "Account with this email already exist, please Login to your account or register with different email";
return View();
}
if (_customer.RegisterCustomer(customer))
{
HttpContext.Session.SetString("email", customer.CustomerEmail);
return RedirectToAction(nameof(Index));
}
else
{
return View();
}
}
You are configuring two mvc middlewares by app.UseMvcWithDefaultRoute(); and app.UseMvc. First choose your expected one and remove another. The key issue is that you are placing app.UseSession(); after app.UseMvcWithDefaultRoute(); which will cause Session middleware fail to execute. Try to move app.UseSession(); before app.UseMvcWithDefaultRoute();.