I am trying to self-host Web API. It works fine when I call requests through my program, where is API controller. But i can't make request through Postman Client. What could be the problem?
Api Controller
public class MyApiController : ApiController
{
public string Get()
{
return "Get";
}
}
Startup.cs
public class Startup
{
public void Configuration(IAppBuilder appBuilder)
{
var config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
}
Program.cs
class Program
{
static void Main(string[] args)
{
string url = "http://localhost:44300/";
using (WebApp.Start<Startup>(url))
{
var client = new HttpClient();
var response = client.GetAsync(url + "api/myapi").Result;
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
Console.ReadLine();
}
}
It looks like your issues are in your main method. In C#, the using statement (link) creates a resource, executes the code in the block, and then disposes of the resource.
In your posted example, your WebApp is disposed right after it prints the response to the console (and before you're able to make requests with your browser).
These edits should allow you to keep the WebApp in-scope in order to play around with the framework.
class Program
{
static void Main(string[] args)
{
string url = "http://localhost:44300/";
using (WebApp.Start<Startup>(url))
{
var client = new HttpClient();
var response = client.GetAsync(url + "api/myapi").Result;
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
Console.WriteLine("WebApp Ready");
Console.ReadLine();
}
Console.WriteLine("WebApp disposed.");
Console.ReadLine();
}
}
Related
My program is for Self hosting a Web API in a Windows Application.
As I dont have much experience in web servie, I request someone's help to fix the problem.
I could make a console application successfully.
But when I change it in to Windows application, my IDE goes stuck with Error "The application is in Break Mode".
Console Program;
using System.Web.Http;
using System.Web.Http.SelfHost;
Main Function:
var config = new HttpSelfHostConfiguration("http://localhost:8080");
config.Routes.MapHttpRoute("API Default", "api/{controller}/{id}", new { id = RouteParameter.Optional });
using (HttpSelfHostServer server = new HttpSelfHostServer(config))
{
server.OpenAsync().Wait();
Console.WriteLine("Press Enter to quit."); // Removed in Win Form
Console.ReadLine(); // Removed in Win Form
}
API Controller Class; I need to receive data here from "FromBody" attribute.
public class FieldsController : ApiController
{
[HttpPost]
public void PostAction([FromBody] Field model)
{
int patientID;
string name;
string age;
patientID = model.patientID;
name = model.patientName;
age = model.patientAge;
}
}
Can you put your error in more detail ?
I have also done in similar way and my one is working.
In the solution of the project I added a new class libraray type project for the webapi.
From the main windowsForm application I am intatiating the webapi.
The webapi project is as below:
using System;
using System.ServiceModel;
using System.Web.Http;
using System.Web.Http.SelfHost;
namespace MYWebAPI
{
public class WebApiProgram : IDisposable
{
private string URL = "http://localhost:1234/";
private HttpSelfHostServer server;
public WebApiProgram()
{
}
public WebApiProgram(string url)
{
this.URL = url;
}
public void Dispose()
{
server.CloseAsync().Wait();
}
public void Start()
{
var config = new HttpSelfHostConfiguration(URL);
config.TransferMode = TransferMode.Streamed;
AddAPIRoute(config);
server = new HttpSelfHostServer(config);
var task = server.OpenAsync();
task.Wait();
//Console.WriteLine("Web API Server has started at:" + URL);
//Console.ReadLine();
}
private void AddAPIRoute(HttpSelfHostConfiguration config)
{
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
From the main() [program.cs file] winform applition I call the webapi start function.
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
private static void Main(string[] args)
{
//Start the webAPI
WebApiProgram.StartMain();
Thread.CurrentThread.CurrentCulture
= Thread.CurrentThread.CurrentUICulture
= CultureInfo.InvariantCulture;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var mainForm = new MainForm();
Application.Run(mainForm);
}
}
I'm trying to use HttpServer to host my Web API 2 site in-process. It is mostly working - I can get/post methods etc. (See https://blogs.msdn.microsoft.com/youssefm/2013/01/28/writing-tests-for-an-asp-net-web-api-service/, "Submitting requests against an in-memory HttpServer", for example). The issue is that the OwinStartup method is never being called and so the OwinContext is null and so I can not get reference to things like the ApplicationUserManager. My understanding is that using HttpServer is essentially identical to hosting the web api in IIS or similar, and so the owin startup method should be called. Here is a code sample:
Client:
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(name: "DefaultApi",
routeTemplate: "{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional, action =
RouteParameter.Optional });
using(var server = new HttpServer(config))
using(var client = new HttpMessageInvoker(server))
{
var address = "http://localhost/account/register";
var r = new RegisterBindingModel() { Email = "abc#abc.com", Password="abc!123", ConfirmPassword = "abc!123" };
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, address))
{
request.Content = new StringContent(JsonConvert.SerializeObject(r), Encoding.Default, "application/json");
using (HttpResponseMessage response = client.SendAsync(request, CancellationToken.None).Result)
{
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
}
}
Startup:
[assembly: OwinStartup(typeof(Test.Startup))]
namespace Test
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
//Not called.. (is called when hosting in IIS)
}
}
}
Controller:
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{
var userManager = UserManager; //This is null.
return Ok();
}
public ApplicationUserManager UserManager
{
get
{
//Request.GetOwinContext() is null.
return _userManager ??Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
Is there something I am missing? How do I get the Startup method to be called?
The project I have created, is an ASP.NET Web API which communicates with a Java Web Service through HttpClient. When I run the Java Web Service, I get the result {"id":2,"content":"Hello, World!"}. When I run the ASP.NET Web API, The ASP.NET Web API gets result from the Java Web Service and displays result as "{\"id\":2,\"content\":\"Hello, World!\"}" in a web page.
How do I display the result in console, which means I create a console application and put in these codes and I want the result to come out in a console and not web page. How do I do that? What are the codes that has to be modified? Someone please kindly do help me thank you so much.
Here are my ASP.NET Codes that I have done so far:
ClientController.cs
public class ClientController : ApiController
{
private ServerClient serverClient = new ServerClient();
public async Task<IHttpActionResult> GET()
{
try
{
var result = await serverClient.content();
return Ok(result);
}
catch (Exception e)
{
var result = "Server is not running";
return Ok(new { ErrorMessage = result });
}
}
}
ServerClient.cs
public class ServerClient
{
private static HttpClient client;
private static string BASE_URL = "http://localhost:8080/";
static ServerClient()
{
client = new HttpClient();
client.BaseAddress = new Uri(BASE_URL);
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<string> content()
{
var endpoint = string.Format("greeting");
var response = await client.GetAsync(endpoint);
return await response.Content.ReadAsStringAsync();
}
}
WebApiConfig.cs
config.Routes.MapHttpRoute(
name: "TestClient",
routeTemplate: "api/testclient",
defaults: new { actcion = "Get", controller = "Client" }
);
static void Main(string[] args)
{
var result = serverClient.content().Result;
Console.WriteLine(result);
}
Please note that using Result or Wait() in async programming might cause deadlock
I'm new on ASP.Net Web API and want to develop a sample to get date time.
I developed two applications.In the first one i Have my API and run it throw Visual Studio and another one is a console application to test the first.
On my API I have:
public class DateTimeController : ApiController
{
public DateTime Get()
{
return DateTime.Now;
}
}
and on my Console application I have this,but i do not know it's correct or not because it doesn't work:
static void Main(string[] args)
{
string baseAddress = "http://localhost:13204/api/DateTime/get";
using (HttpClient httpClient = new HttpClient())
{
Task<String> response =
httpClient.GetStringAsync(baseAddress);
}
Console.ReadLine();
}
Quick watch on response:
response.Status=WaitingForActivation
response.id=4
response.AsyncState=null
WebApiConfig.cs
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 }
);
}
RouteConfig.cs
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "DateTime", action = "Get", id = UrlParameter.Optional }
);
}
}
Several issues here.
HttpClient.GetStringAsync returns a Task<string> but you are not even assigning the results to a variable (or at least you weren't when you first posted the question). With methods that return a Task, you need to await them or wait on them until the task is finished. A lot of methods for doing that in a console app are described here. I'm going to pick one and show you how to implement it.
static void Main(string[] args)
{
var cts = new CancellationTokenSource();
System.Console.CancelKeyPress += (s, e) =>
{
e.Cancel = true;
cts.Cancel();
};
MainAsync(args, cts.Token).Wait();
}
static async Task MainAsync(string[] args, CancellationToken token)
{
string baseAddress = "http://localhost:13204/api/DateTime";
using (var httpClient = new HttpClient())
{
string response = await httpClient.GetStringAsync(baseAddress);
}
}
The response variable will be a string that contains the datetime wrapped in JSON. You can then use your favorite JSON parsing library (I like Json.NET) to obtain the value.
Notice that it wasn't necessary to specify the specific action method in the URL, because we sent an HTTP GET request, and since that action method started with "Get" the framework is smart enough to know it should map to that action method.
This is a follow-up on an earlier question regarding using HttpClient with Web API performing authentication using a custom Message Handler.
I can request data from the server using the provided solution, but now I am having trouble posting JSON data to the server. Whenever I try posting data to the Web API I am returned an Internal Server Error response code.
Here is the code on the client side:
using (var httpClient = new HttpClient())
{
var request = new HttpRequestMessage();
request.Headers.Add("X-Token", UserSession.GlobalInstance.SecurityToken);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(_apiBaseAddress + "api/User");
request.Content = new ObjectContent<UserDTO>(userDTO, new JsonMediaTypeFormatter());
var response = httpClient.SendAsync(request).Result;
if (response.IsSuccessStatusCode)
{
// handle result code
}
throw new Exception(String.Format("Server generated error response: {0}", response.StatusCode));
}
The declaration for the controller method:
public class UserController : ApiController
{
public long Post(UserDTO userDTO)
{
// create user and return custom result
// code (e.g. success, duplicate email, etc...)
}
}
(I've also added [FromBody] to the method parameter, but end up with the same result).
A snapshot of the code for my message handler and routing configuration can be found here.
Your code works as expected...
The server side.
Create a console application and run NuGet
Install-Package Microsoft.AspNet.WebApi.OwinSelfHost
Program.cs
internal class Program
{
private static IDisposable _server;
private static void Main(string[] args)
{
_server = WebApp.Start<Startup>("http://localhost:12345");
Console.ReadLine();
_server.Dispose();
}
}
Startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
}
}
WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var userTokenInspector = new UserTokenInspector {InnerHandler = new HttpControllerDispatcher(config)};
config.Routes.MapHttpRoute(
"UserAuthenticationApi",
"api/{controller}/Authenticate",
new {controller = "User", action = "Authenticate"},
null
);
config.Routes.MapHttpRoute(
"DefaultApi",
"api/{controller}/{id}",
new {id = RouteParameter.Optional},
null,
userTokenInspector
);
}
}
UserTokenInspector.cs
public class UserTokenInspector : DelegatingHandler {
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken) {
const string TOKEN_NAME = "X-Token";
if (!request.Headers.Contains(TOKEN_NAME)) {
return Task.FromResult(request.CreateErrorResponse(HttpStatusCode.Unauthorized,
"Request is missing authorization token."));
}
try {
//var token = UserToken.Decrypt(request.Headers.GetValues(TOKEN_NAME).First());
// validate token
// ...
// ...
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("alex"), new string[] { });
}
catch {
return Task.FromResult(request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid token."));
}
return base.SendAsync(request, cancellationToken);
}
}
UserController.cs
public class UserController : ApiController
{
public long Post(UserDTO userDTO)
{
// create user and return custom result
// code (e.g. success, duplicate email, etc...)
return 1;
}
}
UserDto.cs
public class UserDTO
{
public string Username { get; set; }
}
ValuesController.cs
public class ValuesController : ApiController
{
public HttpResponseMessage Get()
{
return Request.CreateResponse(HttpStatusCode.OK, "yay");
}
}
The Client... create a Console application and run NuGet:
Install-Package Microsoft.AspNet.WebApi.Client
Program.cs
internal class Program
{
private static void Main(string[] args)
{
var request = new HttpRequestMessage();
request.Headers.Add("X-Token", "token");
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Method = HttpMethod.Post;
var baseAddress = "http://localhost:12345/";
request.RequestUri = new Uri(baseAddress + "api/User");
var userDto = new UserDTO() {Username = "Alex"};
request.Content = new ObjectContent<UserDTO>(userDto, new JsonMediaTypeFormatter());
var httpClient = new HttpClient();
var response = httpClient.SendAsync(request).Result;
if (response.IsSuccessStatusCode)
{
// handle result code
Console.WriteLine(response.StatusCode);
Console.ReadLine();
}
}
}