I created a Web API (Microsoft.AspNet.WebApi v5.2.7) targeted to .NET Framework 4.6.2 within a single project that included the default Help page MVC (Microsoft.AspNet.Mvc v5.2.7).
I created an ApiController to handle regular HTTP requests
using System.IO;
using System.Net;
using System.Threading;
using System.Web.Http;
using Project1.Models;
namespace Project1.Controllers
{
public class ProjectController : ApiController
{
// ... code ...
}
}
I eventually needed to self-host it in a Windows service. I was able to do this with OWIN (Microsoft.AspNet.WebApi.OwinSelfHost v5.2.9) by creating a second project, Project2, and adding Project1 as a reference in it. Project2 uses a startup like this
using System;
using System.Web.Http;
using Owin;
using Project1;
namespace Project2.Service
{
public class Startup
{
// reference controller so it's discoverable and can be used by service
Type projectControllerType = typeof(Project1.Controllers.ProjectController);
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
}
}
The service itself for Project2 is basic for this type of project. It starts and stop the web app disposable.
using System;
using System.ServiceProcess;
using Microsoft.Owin.Hosting;
namespace Project2.Service
{
public partial class Project2Service : ServiceBase
{
public string BaseAddress = "http://+:65432/";
private IDisposable _server = null;
public Project2Service()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
_server = WebApp.Start<Startup>(url: BaseAddress);
}
protected override void OnStop()
{
if (_server != null)
{
_server.Dispose();
}
base.OnStop();
}
}
}
Now I wanted to add a /Help route, which comes with WebApi project in the Areas directory
Is there a way to implement this and make the help page callable from my self-hosted service?
I found in the Global.asax it calls AreaRegistration.RegisterAllAreas().
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace Project1
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
I tried calling the AreaRegistration from the service startup
using System.Web.Mvc;
namespace Project2.Service
{
public class Startup
{
// reference controller so it's discoverable and can be used by service
Type projectControllerType = typeof(Project1.Controllers.ProjectController);
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
AreaRegistration.RegisterAllAreas();
appBuilder.UseWebApi(config);
}
}
}
This would cause an exception of This method cannot be called during the application's pre-start initialization phase.
I'm not sure how to go about this. Can I even implement pages with a self-hosted WebAPI?
Related
In Visual Studio 2019, I created an ASP.NET Web API project. I created a Web API 2 controller. I followed this link 1 and link 2 to implement dependency injection using Unity.
I have shared the code according to link 1 but it is not working. I get an error in method GetService(Type serviceType) of UnityResolver (which I copied from first link).
Error is:
Exception thrown: 'Unity.ResolutionFailedException' in Unity.Container.dll
I checked this using breakpoints. It is returning null although container is not null.
I have been searching this so long. I don't understand where it is wrong or I did something wrong.
I am new to .NET Framework and also to programming. Any help or advice appreciated.
public object GetService(Type serviceType)
{
try
{
return container.Resolve<Type>();
//return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
MyAPIController.cs
public class MyAPIController : ApiController
{
private IAgent agent;
public MyAPIController (IAgent _agent)
{
this.agent= _agent;
}
[HttpPost]
[Route("AgentService")]
public string GetAgentServices([FromBody] InputData inputData)
{
return "nothing";
}
}
WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
var container = new UnityContainer();
container.RegisterType<IAgent, Agent>();
config.DependencyResolver = new UnityResolver(container);
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Global.asax.cs
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
Was coaching a colleague on Web API. Just trying to run the default Web API template out of the Visual Studio box, as it were...not even doing anything fancy. A default (Get) call to my API (api/{controller}/{id}) keeps returning the MVC home view instead of the contents of the Get method in my API controller.
namespace WebAPI.Controllers
{
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
...
namespace WebAPI
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
namespace WebAPI
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
I've looked far and wide across the 'Net but can't find anything address my specific problem.
I expected the default value1, value2, etc. Instead, the MVC home view keeps returning instead.
I'm using angular 5 and C# API , and I'm trying to implement SignalR for push notifications ; and I'm stuck on this error "Access-Control-Allow-Origin"
I'm using ng-signalr on angular5
I did something wrong and i don't know where
startup.cs
using Owin;
using System.Web.Http;
using System.Web.Http.Cors;
using Microsoft.AspNet.SignalR;
namespace App5
{
public class Startup
{
// This code configures Web API. The Startup class is specified as a type
// parameter in the WebApp.Start method.
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
// Enable attribute based routing
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}/{action}/{code}",
defaults: new { id = RouteParameter.Optional , action = RouteParameter.Optional, code = RouteParameter.Optional}
);
appBuilder.UseWebApi(config);
appBuilder.MapSignalR();
}
}
}
Ng2SignalRHub.cs
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace App5
{
[Authorize]
[HubName("Ng2SignalRHub")]
public class Ng2SignalRHub : Hub
{
public override Task OnConnected()
{
Trace.TraceInformation("Ng2SignalRHub - OnConnected");
var user = GetAuthenticatedUser();
Clients.All.OnUserConnected(user);
return base.OnConnected();
}
private string GetAuthenticatedUser()
{
var username = Context.QueryString["user"];
if (string.IsNullOrWhiteSpace(username))
throw new System.Exception("Failed to authenticate user.");
Trace.TraceInformation("GetAuthenticatedUser :" + username);
return username;
}
}
}
Please can anyone has the solution for this issue
thanks in advance
Take a look at this link and see if it helps: https://github.com/aspnet/SignalR/issues/1400
Since SignalR is in preview with asp.net core 2.1 you have to make sure that all versions of the client packages match. You should also be configuring a CORS Policy
In ConfigureServices:
services.AddCors(options => options.AddPolicy("CorsPolicy", builder =>
{
builder
.AllowAnyMethod()
.AllowAnyHeader()
.WithOrigins("http://localhost:50000");
}));
services.AddSignalR();
In Configure:
app.UseCors("CorsPolicy");
I have a webapi2 project and I want to selfhost this api in another project and call the methods with a httpClient. Here is my code:
namespace TestSelfHosting.Controllers
{
public class ProductsController : ApiController
{
[HttpGet]
public string GetProduct()
{
return "test";
}
}
}
And the code from the test project:
namespace TestSelfHosting.Tests
{
public class Startup
{
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
}
}
namespace TestSelfHosting.Tests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
const string baseAddress = "http://localhost:9000/";
// Start OWIN host
using (WebApp.Start<Startup>(url: baseAddress))
{
// Create HttpCient and make a request to api/values
HttpClient client = new HttpClient();
var response = client.GetAsync(baseAddress + "api/products").Result;
var content = response.Content.ReadAsStringAsync().Result;
}
}
}
}
But when I'm calling client.GetAsync method, is throwing an error (404, not found). Is this possible to achieve or am I doing something wrong?
I've followed the tutorial from here
Have you referenced your webapi2 project in the self-host project (test project)?
If not, go to your self-host project -> references -> add reference -> locate your webapi2.dll and add it (you must build your webapi2 project beforehand to “generate” the dll file)
I am trying to get a web api set up that will use RESTful services. I am following this guide.
Getting Started with ASP.NET Web API 2 (C#)
I am also following this guide for setting up Entity Framework.
Getting Started with Entity Framework 6 Code First using MVC 5
When I run a Composer in Fiddler. I get the webpage for Home.aspx
Here is the code for my controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebServer.z_Repository;
using WebServer.z_Models;
namespace WebServer.z_Controllers
{
[Route("api/Locations")]
public class LocationsController : ApiController
{
// GET api/<controller>
static IlocationsRepository LocationsRepo;
public LocationsController(IlocationsRepository _repo)
{
if (_repo == null) { throw new ArgumentNullException("_repo"); }
LocationsRepo = _repo;
}
[HttpGet]
public IEnumerable<Location> GetAll()
{
return LocationsRepo.GetAll();
}
}
}
I put a breakpoint on the GetAll() and that breakpoint was never hit. This tells me that the controller isn't registered somewhere. But the guide doesn't say anything about where it should be registered.
I created a Global.asax.cs page even though this is not in the guide. But I am unsure of where to go from here.
Code for Global.asax.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
namespace WebServer
{
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
}
protected void Session_Start(object sender, EventArgs e)
{
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
}
}
}
Here is a snippet showing the response in the Fiddler
Home is showing because according to the URL you showed in Fiddler:
GET Home.aspx/api/locations
it is being told to go to Home.aspx
You are using attribute routing but have not shown any setup for it.
Reference: Attribute Routing in ASP.NET Web API 2
Your controller should be:
[RoutePrefix("api/Locations")]
public class LocationsController : ApiController
{
IlocationsRepository locationsRepo;
public LocationsController(IlocationsRepository _repo)
{
if (_repo == null) { throw new ArgumentNullException("_repo"); }
this.locationsRepo = _repo;
}
//GET api/locations
[HttpGet]
[Route(""}]
public IEnumerable<Location> GetAll()
{
return locationsRepo.GetAll();
}
}
Your WebApiConfig.cs:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Attribute routing.
config.MapHttpAttributeRoutes();
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
and in your global, include
protected void Application_Start()
{
// Pass a delegate to the Configure method.
GlobalConfiguration.Configure(WebApiConfig.Register);
}
Now in order to hit locations web api you will need to call
GET api/location
Host: localhost:59104
which works out to http://localhost:59104/api/locations