Multiple actions were found that match the request - WebApi - asp.net-web-api

I have added WebApi to an existing MVC app and create a controller with a post method. I have one route configured in the webapiconfig. When I use Fiddler to post to the controller, I am receiving the "Multiple Actions" error. my ApiConfig and Controller are posted below. There is some Ioc and DI going on with Ninject. Do I need to add different routes definitions, or is this about the data being posted?
webapiconfig.cs
public static void Register(HttpConfiguration config)
{
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
config.Routes.MapHttpRoute(
name: "Materials",
routeTemplate: "api/materials/{id}",
defaults: new { controller = "materials", id = RouteParameter.Optional }
);
}
MaterialController.
using ????.Info.DAL;
using ????.Info.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using IdentitySample.Models;
namespace ????.Info.Controllers.Api
{
public class MaterialsController : BaseApiController
{
public MaterialsController(I????Repository repo)
:base(repo)
{
}
[Route("api/materials/")]
public IEnumerable<MaterialModel> Get()
{
IQueryable<MaterialEntities.Materials> query;
query = TheRepository.GetAllMaterials();
var results = query
.ToList()
.Select(s => TheModelFactory.Create(s));
return results;
}
[Route("api/materials/{id:int}")]
public HttpResponseMessage GetMaterial(int id)
{
try
{
var material = TheRepository.GetMaterial(id);
if (material != null)
{
return Request.CreateResponse(HttpStatusCode.OK, TheModelFactory.Create(material));
}
else
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
}
catch (Exception ex)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
}
}
[HttpPost]
public HttpResponseMessage Post([FromBody] MaterialModel materialModel)
{
try
{
var entity = TheModelFactory.Parse(materialModel);
if (entity == null) Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not read MaterialType/Organization from body");
if (TheRepository.Insert(entity) && TheRepository.SaveAll())
{
return Request.CreateResponse(HttpStatusCode.Created, TheModelFactory.Create(entity));
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Could not save to the database.");
}
}
catch (Exception ex)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
}
}
public MaterialEntities.Materials Parse(MaterialModel materialmodel)
{
try
{
var material = new MaterialEntities.Materials()
{
Name = materialmodel.Name,
Description = materialmodel.Description,
DateCreated = materialmodel.DateCreated,
};
return material;
}
catch (Exception)
{
return null;
}
}
}
}

Ok, thanks for all the help on this. This was fixed by adding config.MapHttpAttributeRoutes(); to the WebApiConfig. I removed the default route definitions since I am going to use AttributeRouting and it's working now.
update: It looks like it is possible to mix Attribute and Convention routing in the WebApiConfig as discussed here So my problem was solved by adding config.MapHttpAttributeRoutes(); to WebApiConfig

Related

ASP.NET Core - Session not getting saved

I'm trying to save my session in ASP.NET Core, but it is not getting saved.
I have looked at other answers, suggesting to change CookiePolicyOptions and nothing has worked so far. I have another project with the exact same code (presumably), and it works there but not in this project.
In my controller I have:
[HttpPost]
public IActionResult AddToPlan(int mealId)
{
PlanCart planCart = GetPlanCart();
planCart.AddItem(mealId);
SavePlanCart(planCart);
// ALWAYS 1
var y = planCart.returnList();
foreach (var x in y)
{
var z = x; // For debug purposes
}
return RedirectToAction("Index");
}
private PlanCart GetPlanCart()
{
PlanCart planCart = HttpContext.Session.GetJson<PlanCart>("PlanCart") ?? new PlanCart();
return planCart;
}
private void SavePlanCart(PlanCart planCart)
{
HttpContext.Session.SetJson("PlanCart", planCart);
}
I have a class with extension methods:
public static class SessionsExtensions
{
public static void SetJson(this ISession session, string key, object value)
{
session.SetString(key, JsonConvert.SerializeObject(value));
}
public static T GetJson<T>(this ISession session, string key)
{
var sessionData = session.GetString(key);
return sessionData == null
? default(T) : JsonConvert.DeserializeObject<T>(sessionData);
}
}
Startup class:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseSession();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
app.UseCookiePolicy();
}
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.AddSession();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddMemoryCache();
I have checked my session. The session DOES exist but every time the count of the PlanCartList is 1 and previous items are lost.
If anybody could help me it would be very much appreciated because I'm losing my mind here!

Integration Test IocManager is Null

I am setting up Integration tests of my Web UI using abp 3.9.0.
I have followed the model at https://github.com/aspnetboilerplate/aspnet-core-template/tree/master/test/AbpCompanyName.AbpProjectName.Web.Tests
Everything compiles and executes, but I get a null reference exception at the following in my Test base class:
protected void UsingDbContext(Action<CentralPortalDbContext> action)
{
using (var context = IocManager.Resolve<CentralPortalDbContext>())
{
action(context);
context.SaveChanges();
}
}
Inspecting the function during debugging, it shows that IocManager is null.
I've tried various permutations in all of the classes with no luck.
Startup.cs:
using System;
using Abp.AspNetCore;
using Abp.AspNetCore.TestBase;
using Abp.Dependency;
using *****.CentralPortal.EntityFrameworkCore;
using *****.CentralPortal.Web.Controllers;
using Castle.MicroKernel.Registration;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using System.Collections.Generic;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.AspNetCore.Authentication.Cookies;
using Abp.Reflection.Extensions;
namespace *****.CentralPortal.Web.Tests
{
public class Startup
{
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddEntityFrameworkInMemoryDatabase();
services.AddMvc()
.PartManager.ApplicationParts.Add(new AssemblyPart(typeof(Web.Startup.CentralPortalWebModule).GetAssembly()));
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie("Cookies")
.AddOpenIdConnect(options => SetOpenIdConnectOptions(options));
services = SetAuthorizations(services);
//Configure Abp and Dependency Injection
return services.AddAbp<CentralPortalWebTestModule>(options =>
{
options.SetupTest();
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
UseInMemoryDb(app.ApplicationServices);
app.UseAbp(); //Initializes ABP framework.
app.UseExceptionHandler("/Error");
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}"
);
});
app.UseAuthentication();
}
private void UseInMemoryDb(IServiceProvider serviceProvider)
{
var builder = new DbContextOptionsBuilder<CentralPortalDbContext>();
builder.UseInMemoryDatabase(Guid.NewGuid().ToString()).UseInternalServiceProvider(serviceProvider);
var options = builder.Options;
var iocManager = serviceProvider.GetRequiredService<IIocManager>();
iocManager.IocContainer
.Register(
Component.For<DbContextOptions<CentralPortalDbContext>>()
.Instance(options)
.LifestyleSingleton()
);
}
private void SetOpenIdConnectOptions(OpenIdConnectOptions options)
{
options.SignInScheme = "Cookies";
options.Authority = "http://localhost:50052";
options.RequireHttpsMetadata = false;
options.ClientId = "centralportal";
options.ClientSecret = "*************";
options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
options.MetadataAddress = $"http://localhost:50052/.well-known/openid-configuration";
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("auditingApi");
options.Scope.Add("ordersApi");
options.Scope.Add("identityApi");
options.Scope.Add("offline_access");
options.Scope.Add("role");
}
//Helper method to add all authorization policies
//Keeps the ConfigureServices method cleaner.
private IServiceCollection SetAuthorizations(IServiceCollection services)
{
services.AddAuthorization(options =>
options
.AddPolicy("TestResults", builder =>
{
builder.RequireClaim("role", new List<string> { "TestResults" });
})
);
services.AddAuthorization(options =>
options
.AddPolicy("Orders", builder =>
{
builder.RequireRole(new[] { "Orders" });
})
);
services.AddAuthorization(options =>
options
.AddPolicy("HomePage", builder =>
{
builder.RequireRole(new[] { "HomePage" });
})
);
services.AddAuthorization(options =>
options
.AddPolicy("Dashboard", builder =>
{
builder.RequireRole(new[] { "Dashboard" });
})
);
services.AddAuthorization(options =>
options
.AddPolicy("UserAdmin", builder =>
{
builder.RequireRole(new[] { "UserAdmin" });
})
);
services.AddAuthorization(options =>
options
.AddPolicy("CustomerAdmin", builder =>
{
builder.RequireRole(new[] { "CustomerAdmin" });
})
);
return services;
}
}
}
WebTestBase:
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Abp.AspNetCore.TestBase;
using *****.CentralPortal.EntityFrameworkCore;
using *****.CentralPortal.Tests.TestDatas;
using AngleSharp.Dom.Html;
using AngleSharp.Parser.Html;
using Microsoft.AspNetCore.Hosting;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Shouldly;
using Abp.Dependency;
namespace *****.CentralPortal.Web.Tests
{
public abstract class CentralPortalWebTestBase : AbpAspNetCoreIntegratedTestBase<Startup>
{
protected static readonly Lazy<string> ContentRootFolder;
//IIocManager _IocManager;
static CentralPortalWebTestBase()
{
ContentRootFolder = new Lazy<string>(WebContentDirectoryFinder.CalculateContentRootFolder, true);
}
protected CentralPortalWebTestBase() : base()
{
UsingDbContext(context => new TestDataBuilder(context).Build());
}
protected override IWebHostBuilder CreateWebHostBuilder()
{
var _ContentRootFolder = new Lazy<string>(WebContentDirectoryFinder.CalculateContentRootFolder, true);
UsingDbContext(context => new TestDataBuilder(context).Build());
return base
.CreateWebHostBuilder()
.UseStartup<Startup>()
.UseContentRoot(_ContentRootFolder.Value);
}
#region Get response
protected async Task<T> GetResponseAsObjectAsync<T>(string url,
HttpStatusCode expectedStatusCode = HttpStatusCode.OK)
{
var strResponse = await GetResponseAsStringAsync(url, expectedStatusCode);
return JsonConvert.DeserializeObject<T>(strResponse, new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
}
protected async Task<string> GetResponseAsStringAsync(string url,
HttpStatusCode expectedStatusCode = HttpStatusCode.OK)
{
var response = await GetResponseAsync(url, expectedStatusCode);
return await response.Content.ReadAsStringAsync();
}
protected async Task<HttpResponseMessage> GetResponseAsync(string url,
HttpStatusCode expectedStatusCode = HttpStatusCode.OK)
{
var response = await Client.GetAsync(url);
response.StatusCode.ShouldBe(expectedStatusCode);
return response;
}
#endregion
#region UsingDbContext
protected void UsingDbContext(Action<CentralPortalDbContext> action)
{
using (var context = IocManager.Resolve<CentralPortalDbContext>())
{
action(context);
context.SaveChanges();
}
}
protected T UsingDbContext<T>(Func<CentralPortalDbContext, T> func)
{
T result;
using (var context = IocManager.Resolve<CentralPortalDbContext>())
{
result = func(context);
context.SaveChanges();
}
return result;
}
protected async Task UsingDbContextAsync(Func<CentralPortalDbContext, Task> action)
{
using (var context = IocManager.Resolve<CentralPortalDbContext>())
{
await action(context);
await context.SaveChangesAsync(true);
}
}
protected async Task<T> UsingDbContextAsync<T>(Func<CentralPortalDbContext, Task<T>> func)
{
T result;
using (var context = IocManager.Resolve<CentralPortalDbContext>())
{
result = await func(context);
context.SaveChanges();
}
return result;
}
#endregion
#region ParseHtml
protected IHtmlDocument ParseHtml(string htmlString)
{
return new HtmlParser().Parse(htmlString);
}
#endregion
}
}
Web Test Module
using Abp.AspNetCore.TestBase;
using Abp.Modules;
using Abp.Reflection.Extensions;
using Castle.MicroKernel.Registration;
using Castle.Windsor.MsDependencyInjection;
using *****.CentralPortal.EntityFrameworkCore;
using *****.CentralPortal.Web.Startup;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace *****.CentralPortal.Web.Tests
{
[DependsOn(
typeof(CentralPortalWebModule),
typeof(CentralPortalEntityFrameworkCoreModule),
typeof(AbpAspNetCoreTestBaseModule)
)]
public class CentralPortalWebTestModule : AbpModule
{
public override void PreInitialize()
{
Configuration.UnitOfWork.IsTransactional = false; //EF Core InMemory DB does not support transactions.
}
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(CentralPortalWebTestModule).GetAssembly());
SetupInMemoryDb();
}
private void SetupInMemoryDb()
{
var services = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase();
var serviceProvider = WindsorRegistrationHelper.CreateServiceProvider(
IocManager.IocContainer,
services
);
var builder = new DbContextOptionsBuilder<CentralPortalDbContext>();
builder.UseInMemoryDatabase().UseInternalServiceProvider(serviceProvider);
IocManager.IocContainer.Register(
Component
.For<DbContextOptions<CentralPortalDbContext>>()
.Instance(builder.Options)
.LifestyleSingleton()
);
}
}
}
Web Test Class:
using System.Threading.Tasks;
using *****.CentralPortal.Web.Controllers;
using Shouldly;
using Xunit;
namespace *****.CentralPortal.Web.Tests.Controllers
{
public class HomeController_Tests: CentralPortalWebTestBase
{
[Fact]
public async Task Index_Test()
{
string url = GetUrl<HomeController>(nameof(HomeController.Index));
//Act
var response = await GetResponseAsStringAsync(
url
);
//Assert
response.ShouldNotBeNullOrEmpty();
}
[Fact]
public async void ShouldOnlyShowHomeMenuWhenNotAuthorized()
{
var response = await GetResponseAsStringAsync(
GetUrl<HomeController>(nameof(HomeController.Index))
);
//Parse the response for menuitems, count them and assert
int menuitemcount = 0;
string statuscode = "";//TODO: Gotta parse the response string to get the code
Assert.Equal(menuitemcount, 2);
}
}
}
I'm not sure why IocManager is null at this point. I'm guessing it's a simple config item I'm missing, but I can't seem to find it or any examples that deviate from what I've got.
Any help would be appreciated.
As Requested: the Full Exception.
[1/29/2019 8:51:46 AM Informational] [xUnit.net 00:00:02.72] System.NullReferenceException : Object reference not set to an instance of an object.
[1/29/2019 8:51:46 AM Informational] [xUnit.net 00:00:02.72] Stack Trace:
[1/29/2019 8:51:46 AM Informational] [xUnit.net 00:00:02.72] C:\ProjectCode\*****\*****_CentralPortal\test\*****.CentralPortal.Web.Tests\CentralPortalWebTestBase.cs(78,0): at *****.CentralPortal.Web.Tests.CentralPortalWebTestBase.UsingDbContext(Action`1 action)
[1/29/2019 8:51:46 AM Informational] [xUnit.net 00:00:02.72] C:\ProjectCode\*****\*****_CentralPortal\test\*****.CentralPortal.Web.Tests\CentralPortalWebTestBase.cs(37,0): at *****.CentralPortal.Web.Tests.CentralPortalWebTestBase.CreateWebHostBuilder()
[1/29/2019 8:51:46 AM Informational] [xUnit.net 00:00:02.72] D:\Github\aspnetboilerplate\src\Abp.AspNetCore.TestBase\AbpAspNetCoreIntegratedTestBase.cs(30,0): at Abp.AspNetCore.TestBase.AbpAspNetCoreIntegratedTestBase`1..ctor()
[1/29/2019 8:51:46 AM Informational] [xUnit.net 00:00:02.72] C:\ProjectCode\*****\*****_CentralPortal\test\*****.CentralPortal.Web.Tests\CentralPortalWebTestBase.cs(28,0): at *****.CentralPortal.Web.Tests.CentralPortalWebTestBase..ctor()
[1/29/2019 8:51:46 AM Informational] [xUnit.net 00:00:02.72] at *****.CentralPortal.Web.Tests.Controllers.HomeController_Tests..ctor()
So it was the following in the web test module. I'm not sure where I got that from, I think it was in an example I pulled from. Commenting out SetupInMemoryDb(); resolved the issue.
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(CentralPortalWebTestModule).GetAssembly());
SetupInMemoryDb();
}
private void SetupInMemoryDb()
{
var services = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase();
var serviceProvider = WindsorRegistrationHelper.CreateServiceProvider(
IocManager.IocContainer,
services
);
var builder = new DbContextOptionsBuilder<CentralPortalDbContext>();
builder.UseInMemoryDatabase().UseInternalServiceProvider(serviceProvider);
IocManager.IocContainer.Register(
Component
.For<DbContextOptions<CentralPortalDbContext>>()
.Instance(builder.Options)
.LifestyleSingleton()
);
}

Using RxJs and Angular 5 in order to deal with server-sent events from Spring Boot

I need to update my Angular UI according to data that is emitted from MySQL thorough Spring for every update that happens in MYSQL DB. But on Angular side, I'm not able to fetch the data.
This is my WebController.java on Springboot:
#GetMapping("/summary")
public SseEmitter Summary(#RequestParam Map<String,String> queryParam,String date, String target) {
Connection conn = null;
List<Map<String, Object>> listOfMaps = null;
Statement stmt = null;
prodDate = queryParam.get("date").replaceAll("\'", "");
prodTarget = queryParam.get("target").replaceAll("\'", "");
final SseEmitter emitter = new SseEmitter();
try{
Class.forName("com.mysql.jdbc.Driver");
System.out.println("Connecting to database...To retrive SUMMARY");
conn = DriverManager.getConnection(DB_URL,USER,PASS);
String query= "SELECT migration_states.state END AS state, migrations.mignum, migrations.projectleader, migrations.productiondate, migrations.installationtiers, "
+ "migrations.targetplatform, migrations.apprelated, migrations.appversion "
+ "FROM (migrations LEFT JOIN migration_states ON migrations.state = migration_states.state_code) "
+ "WHERE migrations.productiondate=? AND migrations.targetplatform=? AND migration_states.state NOT LIKE '%Cancelled%' ";
QueryRunner queryRunner = new QueryRunner();
listOfMaps = queryRunner.query(conn, query, new MapListHandler(), prodDate, prodTarget);
emitter.send(listOfMaps,MediaType.APPLICATION_JSON);
System.out.println(emitter);
conn.close();
}
catch (SQLException se) {
se.printStackTrace();
emitter.completeWithError(se);
return emitter;
}catch(Exception e){
e.printStackTrace();
emitter.completeWithError(e);
return emitter;
}finally {
DbUtils.closeQuietly(conn);
}
emitter.complete();
return emitter;
}
Which gives me the following result, when triggered in Postman
http://localhost:8080/api/summary?date=2018-06-06&target=Production
data:[{"state":"Completed","mignum":146289,"projectleader":"Eric Lok","productiondate":"2018-06-06","installationtiers":"Windows Server","targetplatform":"Production","apprelated":"UPS Pickup Point Web Application","appversion":"2.25"},
{"state":"Completed","mignum":146381,"projectleader":"James Rice","productiondate":"2018-06-06","installationtiers":"Linux Web WL10","targetplatform":"Production","apprelated":"Content Only","appversion":""},
{"state":"Completed","mignum":146461,"projectleader":"Nishith Jani","productiondate":"2018-06-06","installationtiers":"Linux BEA WL12","targetplatform":"Production","apprelated":"Tracking Comp","appversion":"1801.20"},
{"state":"Completed","mignum":146574,"projectleader":"Nishith Jani","productiondate":"2018-06-06","installationtiers":"Linux BEA WL12","targetplatform":"Production","apprelated":"Tracking Comp","appversion":"01-00-07-17"}]
This is my Angular Service call subscribing to WebController
import { Injectable } from '#angular/core';
import { Http, Response, Headers, RequestOptions } from '#angular/http';
import { map } from 'rxjs/operators';
#Injectable()
export class DashboardDataService {
public baseUrl = 'http://localhost:8080/api';
public headers = new Headers({'Content-Type': 'application/json' });
public options = new RequestOptions({headers: this.headers});
constructor(private _http: Http) { }
getSummary(_date, _target) {
return this._http.get(this.baseUrl + '/summary?date='+_date+"&target="+_target, this.options).pipe(map((response: Response) => response.json()));
}
}
This is my component
import { Component, OnInit, OnDestroy } from '#angular/core';
import { DashboardDataService } from '../shared-service/dashboard-data.service';
#Component({
selector: 'app-dashboard-view',
templateUrl: './dashboard-view.component.html',
styleUrls: ['./dashboard-view.component.css']
})
export class DashboardViewComponent implements OnInit, OnDestroy {
constructor(private _dashboardService: DashboardDataService) { }
ngOnInit() {
this._dashboardService.getSummary(this._date, this._target).addEventListener((dashboardataa) => {
this.dashboardataa = dashboardataa;
console.log("this.dashboardata-->", this.dashboardataa);
}, (error) => { console.error('SERVER ERROR'); });
}
}
But the issue is that the
console.log("this.dashboardata-->", this.dashboardataa);
Never gets printed. I'm new to Spring, Ssemitter & Rxjs, so I'mdoing something wrong here. Which I'm not able to figure out.
Reading some blogs said me to use addEventListener,but when I try this
this._dashboardService.getSummary(this._date, this._target).addEventListener((dashboardataa) => {
this.dashboardataa = dashboardataa;
console.log("this.dashboardata-->", this.dashboardataa); }
I get error saying
error TS2339: Property 'addEventListener' does not exist on type
'Observable'.
Can anyone help me how to write correct code on Angular side, to get the json data, which will emiited, when the update happens on Server side.
You should use just Observables:
getSummary(_date, _target) : Observable<any> {
return this._http.get(this.baseUrl + '/summary?date='+_date+"&target="+_target,
this.options);
}
and in your component subscribe to it:
this._dashboardService.getSummary(this._date, this._target).subscribe((dashboardataa) => {
this.dashboardataa = dashboardataa;
console.log("this.dashboardata-->", this.dashboardataa);
}, (error) => { console.error('SERVER ERROR'); });
}
}

SwaggerUI not working with API versioning

I'm trying to use SwaggerUI, but I'm having some problems.
When I call http://mysite.com/api/swagger I get this:
{
"apiVersion":"4.0.0.0",
"swaggerVersion":"2.0",
"basePath":"http://mysite.com",
"resourcePath":null,
"apis":
[
{
"path":"/api/docs/V1.Foo",
"description":"Foo V1.",
"operations":[]
},
{
"path":"/api/docs/V2.Foo",
"description":"Foo V2.",
"operations":[]
}
]
}
But, when I call http://mysite.com/api/docs/V1.Foo or http://mysite.com/api/docs/V2.Foo I get this:
<Error>
<Message>
The requested resource does not support http method 'GET'.
</Message>
</Error>
It look like I'm calling my API, but I'm trying to get the API documentation.
All my controllers implement System.Web.Http.ApiController.
This is my WebApiConfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
config.Routes.MapHttpRoute(
name: "SwaggerApi",
routeTemplate: "api/docs/{controller}",
defaults: new { swagger = true }
);
config.Routes.MapHttpRoute(
name: "Swagger",
routeTemplate: "api/swagger",
defaults: new { controller = "swagger" }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{version}/{controller}/{id}",
defaults: new { id = RouteParameter.Optional, version = "v1" }
);
config.Filters.Add(new SwaggerActionFilter());
try
{
config.Services.Replace(typeof(IDocumentationProvider),
new XmlCommentDocumentationProvider(HttpContext.Current.Server.MapPath("~/bin/XmlDocument.XML")));
}
catch (FileNotFoundException)
{ }
//My version selector
config.Services.Replace(typeof(IHttpControllerSelector), new VersionControllerSelector(config));
config.Filters.Add(new VersionNoHeaderAttribute());
}
}
And this is my IHttpControllerSelector implementation (VersionControllerSelector):
...
public HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
var routeData = request.GetRouteData();
if (routeData == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
string version;
if (GetRouteVariable<bool>(routeData, "swagger"))
{
version = ""; // Here I have the version and controller name.
}
else if (request.RequestUri.ToString().ToLower().EndsWith("swagger"))
{
version = "net."; // Net.Swagger
}
else
{
version = GetRouteVariable<string>(routeData, VersaoKey);
if (version == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
version = string.Format(CultureInfo.InvariantCulture, "{0}.", version); // V1.MyControler
}
var controllerName = GetRouteVariable<string>(routeData, ControllerKey);
if (controllerName == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
var key = version + controllerName;
HttpControllerDescriptor controllerDescriptor;
if (_controllers.Value.TryGetValue(key, out controllerDescriptor))
{
return controllerDescriptor;
}
throw new HttpResponseException(HttpStatusCode.NotFound);
}
...
SwaggerActionFilter doesn't get my request when I call http://mysite.com/api/docs/"some-controller".
If I use SwaggerUI in another Solution without versioning, I'm able to get all documentations.
I know that maybe my versioning selector is wrong, but I dont't know what is wrong.

Can I display contents of Application or Cache objects using Glimpse in an MVC project?

The ASP.NET WebForms trace output has a section for Application State. Is it possible to see the same using Glimpse?
In my home controller's Index() method, I tried adding some test values, but I don't see the output in any of the Glimpse tabs.
ControllerContext.HttpContext.Application.Add("TEST1", "VALUE1");
ControllerContext.HttpContext.Cache.Insert("TEST2", "VALUE2");
I didn't see anything in the documentation either.
I don't think that there is an out-of-the-box support for this, but it would be trivial to write a plugin that will show this information.
For example to show everything that's stored in the ApplicationState you could write the following plugin:
[Glimpse.Core.Extensibility.GlimpsePluginAttribute]
public class ApplicationStateGlimpsePlugin : IGlimpsePlugin
{
public object GetData(HttpContextBase context)
{
var data = new List<object[]> { new[] { "Key", "Value" } };
foreach (string key in context.Application.Keys)
{
data.Add(new object[] { key, context.Application[key] });
}
return data;
}
public void SetupInit()
{
}
public string Name
{
get { return "ApplicationState"; }
}
}
and then you get the desired result:
and to list everything that's stored into the cache:
[Glimpse.Core.Extensibility.GlimpsePluginAttribute]
public class ApplicationCacheGlimpsePlugin : IGlimpsePlugin
{
public object GetData(HttpContextBase context)
{
var data = new List<object[]> { new[] { "Key", "Value" } };
foreach (DictionaryEntry item in context.Cache)
{
data.Add(new object[] { item.Key, item.Value });
}
return data;
}
public void SetupInit()
{
}
public string Name
{
get { return "ApplicationCache"; }
}
}

Resources