Cannot run a restfull server in a ASP.Net without MVC - c#

I'm trying to run a simple restfull server in a simple asp.net application without the mvc(following this tutorial : http://www.codeproject.com/Articles/769671/Web-API-without-MVC
(which will trun into a online portal).
here is my class :
public class Foods
{
public string FoodName { get; set; }
public string Price { get; set; }
public string Type { get; set; }
public string Content { get; set; }
public Foods()
{
}
}
and here is my controller:
public class FoodController : ApiController
{
public List<Foods> _productList;
public List<Foods> GetProductList()
{
_productList = new List<Foods>{
new Foods{FoodName= "pizza",Content= "bread cheese",Type="Main",Price="100"},
new Foods{FoodName= "rice",Content= "rice and ...",Type="Main",Price="100"}
};
return _productList;
}
}
and here is my asp.net page code(it is simple nothing to show):
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
var config = new HttpSelfHostConfiguration("http://localhost:8080/");
config.Routes.MapHttpRoute(
"API Default", "api/{controller}/{id}",
new { id = System.Web.Http.RouteParameter.Optional });
using (HttpSelfHostServer server = new HttpSelfHostServer(config))
{
server.OpenAsync().Wait();
}
}
}
when i run it there is no error and the blank page is shown
and here is the client which is a simple c# form with a list box and a button:
private void button1_Click(object sender, EventArgs e)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:8080/");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
try
{
HttpResponseMessage response = client.GetAsync("api/foods").Result;
if (response.IsSuccessStatusCode)
{
// Parse the response body. Blocking!
var foods = response.Content.ReadAsAsync<IEnumerable<Foods>>().Result;
foreach (Foods food in foods)
{
string foodinfo = food.FoodName + " " + food.Content + " " + food.Type + " " + food.Price;
listBox1.Items.Add(foodinfo);
}
}
}
catch (Exception ex)
{
textBox1.Text = ex.ToString();
}
}
but when i run the client and click the button i get this error:
System.AggregateException: One or more errors occurred.
System.Net.Sockets.SocketException: No connection could be made
because the target machine actively refused it 127.0.0.1:8080

There could be one or more reason for it.
1) Make sure that the port 8080 is not consumed by other application, Try running on different port.
try client.BaseAddress = new Uri("http://localhost:9090/");
2) By default, listening at a particular HTTP address requires administrator privileges. When you run the application, therefore, you might get an error: "HTTP could not register URL http://+:8080/".To avoid this error, run Visual Studio with elevated administrator permissions.
3) Make sure that both projects are running parallelly. If not do it.
Go to Solution properties -> Common properties -> Startup Project and select Multiple startup projects

Related

Can't get a valid response from a REST web service using System.Net.Http.HttpClient

I am using this test method (and helper class) to verify the response from an external web service:
[TestMethod]
public void WebServiceReturnsSuccessResponse()
{
using (var provider = new Provider(new Info()))
using (var result = provider.GetHttpResponseMessage())
{
Assert.IsTrue(result.IsSuccessStatusCode);
}
}
private class Info : IInfo
{
public string URL { get; set; } =
"https://notreallythe.website.com:99/service/";
public string User { get; set; } = "somename";
public string Password { get; set; } = "password1";
}
I can't get this test to pass; I always get a 500 - Internal Server Error result. I have connected via an external utility (Postman) - so the web service is up and I can connect with the url & credentials that I have.
I think the problem is in my instantiation of the HttpClient class, but I can't determine where. I am using Basic authentication:
public class Provider : IProvider, IDisposable
{
private readonly HttpClient _httpClient;
public Provider(IInfo config){
if (config == null)
throw new ArgumentNullException(nameof(config));
var userInfo = new UTF8Encoding().GetBytes($"{config.User}:{config.Password}");
_httpClient = new HttpClient
{
BaseAddress = new Uri(config.URL),
DefaultRequestHeaders =
{
Accept = { new MediaTypeWithQualityHeaderValue("application/xml")},
Authorization = new AuthenticationHeaderValue(
"Basic", Convert.ToBase64String(userInfo)),
ExpectContinue = false,
},
};
}
public HttpResponseMessage GetHttpResponseMessage()
{
return _httpClient.GetAsync("1234").Result;
}
}
The response I get back appears to go to the correct endpoint; the RequestUri in the response looks exactly like I expect, https://notreallythe.website.com:99/service/1234.
You need to load up Fiddler and do a recording of the HTTP traffic when this operation succeeds (through the browser).
Then, load up your code, stand up another instance (or window) of Fiddler, and do the same thing with your code. Now, compare the two Fiddler windows to see what is different.
You only need to compare those things in Fiddler that are highlighted in blue. You can ignore the other communications.

ASP.NET Self hosted Web API with IE – This page cannot be displayed

I am trying to invoke my service locally but IE and Edge are not able to find it.
Below is the code snippet I have and my console app is working without any error.
Program.cs
public class Program
{
static void Main()
{
string baseAddress = "http://127.0.0.1:8080/";
// Start OWIN host
using (WebApp.Start(url: baseAddress))
{
Console.WriteLine("Service Listening at " + baseAddress);
System.Threading.Thread.Sleep(-1);
}
}
}
Startup.cs
public class Startup
{
public void Configuration(IAppBuilder appBuilder)
{
HttpConfiguration config = new HttpConfiguration();
config.EnableCors();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
}
WebController.cs
public class Web
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class WebController : ApiController
{
Web[] websites = new Web[]
{
new Web { Id = 1, Name = "XYZ", Description = "XYZ"},
new Web { Id = 2, Name = "ABC", Description = "ABC"}
};
// GET api/Web
public IEnumerable Get()
{
return websites;
}
// GET api/Web/5
public Web Get(int id)
{
try
{
return websites[id];
}
catch (Exception e)
{
return new Web();
}
}
// POST api/values
public void Post([FromBody]string value)
{
Console.WriteLine("Post method called with value = " + value);
}
// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
Console.WriteLine("Put method called with value = " + value);
}
// DELETE api/values/5
public void Delete(int id)
{
Console.WriteLine("Delete method called with id = " + id);
}
}
I am invoking my service on IE like everyone does: http://127.0.0.1:8080/api/web to GET entire Web Object.
I have installed two additional packages, OWIN and CORS.
Could someone help find a solution for this issue.
I have just tried and your api works correctly in Edge and Chrome. It can be that IE don't send correct Accept header which causes to either server to return wrong result or error or IE cannot interpret the response. Actually, I have check and IE offers to save json file because it cannot display it correctly.
To show it explicitly I have modified you code a bit:
public IHttpActionResult Get(string type = null)
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
if (type == "json")
{
response.Content = new StringContent(JsonConvert.SerializeObject(websites));
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
}
else if (type == "xml")
{
response.Content = new StringContent("<xmlTag>Value</xmlTag>");
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/xml");
}
return ResponseMessage(response);
}
Try follow http://127.0.0.1:8080/api/web?type=json and http://127.0.0.1:8080/api/web?type=xml urls and check yourself.

D2L Valence: Auto-authentication in c# with app & user id/key

the below is my code.
I'm building a c# window app to obtain some information from url without having to log in but auto-log in.
It's window app form that will output course offerings when user clicks the accept button. This code is based on valence-client-side sample code. I want this app to log in with the app id/key pair and user id/key pair and get course offerings and output them. But, when I run this program, it just stops var ctx = httpListener.GetContext(); at this line. I don't want it to open a browser but want to get auto-log in with app and user id/key pair in c#, and get json response from the url. so users do not have to log in.
namespace CourseOfferingWindow
{
class CourseOfferingResponse
{
public string Identifier { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public bool IsActive { get; set; }
public string Path { get; set; }
public object StartDate { get; set; }
public object EndDate { get; set; }
public string CourseTemplate { get; set; }
public string Semester { get; set; }
public string Department { get; set; }
}
public partial class CourseOfferingWindowForm : Form
{
public CourseOfferingWindowForm()
{
InitializeComponent();
}
private static ID2LUserContext InterceptUserTokens(HostSpec host, ID2LAppContext appContext)
{
// Start HTTP server and listen for the redirect after a successful auth
var httpListener = new HttpListener();
httpListener.Prefixes.Add("http://localhost:31337/result/");
httpListener.Start();
// This call blocks until we get a response
var ctx = httpListener.GetContext();
// The LMS returns the user tokens via query parameters to the value provided originally in x_target
// TODO: deal with "failed to login" case
var userContext = appContext.CreateUserContext(ctx.Request.Url, host);
// Send some JavaScript to close the browser popup
// This is not 100% effective: for example, Firefox will ignore this.
const string RESPONSE = "<!doctype html><meta charset=\"utf-8\"><script>window.close();</script><h1>You may now close your window</h1><p>You may or may not see this message, depending on your browser</p>";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(RESPONSE);
ctx.Response.ContentType = "text/html";
ctx.Response.ContentLength64 = buffer.Length;
ctx.Response.OutputStream.Write(buffer, 0, buffer.Length);
ctx.Response.OutputStream.Close();
httpListener.Stop();
return userContext;
}
private static void DoApiStuff(string host, ID2LUserContext userContext)
{
const string COURSEOFFERING_ROUTE = "/d2l/api/lp/1.0/courses/644849";
var client = new RestClient(host);
var valenceAuthenticator = new D2L.Extensibility.AuthSdk.Restsharp.ValenceAuthenticator(userContext);
var request = new RestRequest(COURSEOFFERING_ROUTE, Method.GET);
valenceAuthenticator.Authenticate(client, request);
var response = client.Execute<CourseOfferingResponse>(request);
Console.WriteLine("Hello, " + {course offerings information} );
}
private void ButtonAccept_Click(object sender, EventArgs e)
{
// This is the LMS we will interact with
var host = new HostSpec("https", "www.foltest.ca", 443);
// The appId/appKey come from our app.config - it is good to seperate access keys from the code that uses them.
// Ideally you wouldn't have production keys committed to source control.
string appId = ConfigurationManager.AppSettings["appId"];
string appKey = ConfigurationManager.AppSettings["appKey"];
// This is the port we will temporarily host a server on to intercept the user tokens after a successful login
int port = int.Parse(ConfigurationManager.AppSettings["serverPort"]);
// Create url for the user to login. If they have already done so they will not actually have to type their password (maybe).
var appContextFactory = new D2LAppContextFactory();
var appContext = appContextFactory.Create(appId, appKey);
var authUrl = appContext.CreateUrlForAuthentication(host, new Uri("http://localhost:" + port + "/result/"));
//OpenBrowser(authUrl);
// This call will block until we have a result
// TODO: you'll want better control flow and error handling here
var userContext = InterceptUserTokens(host, appContext);
// Now we can call Valence
DoApiStuff(host.Scheme + "://" + host.Host + ":" + host.Port, userContext);
// Pause the terminal
Console.ReadKey();
}
}
}
any kind of help will be appreciated. Thanks, Phillip
Instead of:
var authUrl = appContext.CreateUrlForAuthentication(host, new Uri("http://localhost:" + port + "/result/"));
//OpenBrowser(authUrl);
// call will block until we have a result
// TODO: you'll want better control flow and error handling here
var userContext = InterceptUserTokens(host, appContext);
// Now we can call Valence
DoApiStuff(host.Scheme + "://" + host.Host + ":" + host.Port, userContext);
do:
const string userId = "a_user_id"; // Use the correct user id
const string userKey = "a_user_key"; // Use the correct user key
var userContext = appContext.CreateUserContext(userId, userKey, host);
DoApiStuff(host.Scheme + "://" + host.Host + ":" + host.Port, userContext);
This assumes you have a Valence user id and key for the user account you want to use at your disposal. If you don't, you need to generate them out-of-band.

Connecting Silverlight client to SignalR server

I've been driving myself nuts trying to resolve this issue so really hoping someone has some insight.
I have a console application which runs/hosts my signalR server.
I have already successfully connected to it using a web(javascript) client and a windows forms client with no trouble at all.
BUT for the life of me I cannot get a silverlight client to connect to it. Initially I was getting a
'System.Security.SecurityException' occurred in Microsoft.Threading.Tasks error
on
await Connection.Start();
I managed to fix that by force sending the clientaccesspolicy file using code i found on a random thread.
THREAD
However the connection still never establishes. The status goes thru connecting, disconnected, connection closed.
I am at my wits end as to why this won't work. Any input is appreciated. Code below.
MainPage.xaml.cs
public partial class MainPage : UserControl
{
private SignalRClient client;
public MainPage()
{
InitializeComponent();
dataGrid1.ItemsSource = new ItemsCollection();
client = new SignalRClient();
client.RunAsync();
Debug.WriteLine("Init Done");
}
}
-
SignalRClient.cs
public class SignalRClient
{
private HubConnection Connection { get; set; }
private IHubProxy HubProxy { get; set; }
const string url = "http://localhost:8080/";
public SignalRClient()
{
}
public async void RunAsync()
{
Connection = new HubConnection(url, useDefaultUrl: true);
Connection.Closed += Connection_Closed;
Connection.StateChanged += ConnectionDidSomething;
HubProxy = Connection.CreateHubProxy("TickerHub");
HubProxy.On<string>("receiveAllData", data => Debug.WriteLine("RECDATA={0}", data));
try
{
await Connection.Start();
}
catch (HttpClientException e)
{
Debug.WriteLine("Unable to connect to server.1 {0}", e.Message);
return;
}
catch (HttpRequestException e)
{
Debug.WriteLine("Unable to connect to server.2 {0}", e.Message);
return;
}
}
-
Server
class Program
{
static void Main(string[] args)
{
string url = "http://localhost:8080/";
using (WebApp.Start(url))
{
Console.WriteLine("SignalR server running on {0}", url);
Console.ReadLine();
}
Console.ReadLine();
}
}
class Startup
{
public void Configuration(IAppBuilder app)
{
Console.WriteLine("Configuration");
//Tried this approach too
/*app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
EnableJSONP = true
};
map.RunSignalR(hubConfiguration);
});*/
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR<ClientAccessPolicyConnection>("/clientaccesspolicy.xml");
}
}
-
TickerHub.cs
public class TickerHub : Hub
{
public override Task OnConnected()
{
string connectionID = Context.ConnectionId;
Console.WriteLine("New Connection:" + connectionID);
InitNewClient(connectionID);
return base.OnConnected();
}
//send all data to newly connected client
public void InitNewClient(string connectionID)
{
}
//client requested all data
public void GetAllData()
{
Console.WriteLine("Get Data Triggered");
Clients.All.receiveAllData("TESTING123");
}
}
I figured it out! Hopefully this helps someone in the future.
Its quite simple. This is what you need to have in your startup class configuration method.
Below that is the code required to send the clientaccesspolicy.xml.
class Startup
{
public void Configuration(IAppBuilder app)
{
// Branch the pipeline here for requests that start with "/signalr"
app.Map("/signalr", map =>
{
// Setup the CORS middleware to run before SignalR.
// By default this will allow all origins. You can
// configure the set of origins and/or http verbs by
// providing a cors options with a different policy.
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
// You can enable JSONP by uncommenting line below.
// JSONP requests are insecure but some older browsers (and some
// versions of IE) require JSONP to work cross domain
EnableJSONP = true
};
// Run the SignalR pipeline. We're not using MapSignalR
// since this branch already runs under the "/signalr"
// path.
map.RunSignalR(hubConfiguration);
});
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR<ClientAccessPolicyConnection>("/clientaccesspolicy.xml");
}
}
-
public class ClientAccessPolicyConnection : PersistentConnection
{
public override Task ProcessRequest(Microsoft.AspNet.SignalR.Hosting.HostContext context)
{
string[] urlArray = context.Request.Url.ToString().Split('/');
string path = urlArray[urlArray.Length - 1];
if (path.Equals("clientaccesspolicy.xml", StringComparison.InvariantCultureIgnoreCase))
{
//Convert policy to byteArray
var array = Encoding.UTF8.GetBytes(ClientAccessPolicy);
var segment = new ArraySegment<byte>(array);
//Write response
context.Response.ContentType = "text/xml";
context.Response.Write(segment);
//Return empty task to escape from SignalR's default Connection/Transport checks.
return EmptyTask;
}
return EmptyTask;
}
private static readonly Task EmptyTask = MakeTask<object>(null);
public static Task<T> MakeTask<T>(T value)
{
var tcs = new TaskCompletionSource<T>();
tcs.SetResult(value);
return tcs.Task;
}
public static readonly string ClientAccessPolicy =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<access-policy>"
+ "<cross-domain-access>"
+ "<policy>"
+ "<allow-from http-request-headers=\"*\">"
+ "<domain uri=\"*\"/>"
+ "</allow-from>"
+ "<grant-to>"
+ "<resource path=\"/\" include-subpaths=\"true\"/>"
+ "</grant-to>"
+ "</policy>"
+ "</cross-domain-access>"
+ "</access-policy>";
}

OAuthException: (#200) The user hasn't authorized the application to perform this action

Using the Facebook C# SDK, I'm getting the following error when I try to post a status update:
OAuthException: (#200) The user hasn't authorized the application to perform this action
I am getting this error only with some users. For some other,status is updating fine. App is successfully getting access for all users.
This is the full code :
public partial class Authorize : Form
{
public Authorize()
{
InitializeComponent();
}
public string ApplicationId
{
get
{
return ConfigurationManager.AppSettings["ApplicationId"];
}
}
public string ExtendedPermissions
{
get
{
return ConfigurationManager.AppSettings["ExtendedPermissions"];
}
}
public string AppSecret
{
get
{
return ConfigurationManager.AppSettings["ApplicationSecret"];
}
}
public string AccessToken { get; set; }
private void LoadAuthorize(object sender, EventArgs e)
{
var destinationURL = String.Format(
#"https://www.facebook.com/dialog/oauth?client_id={0}&scope={1}&redirect_uri=http://www.facebook.com/connect/login_success.html&response_type=token",
this.ApplicationId,
this.ExtendedPermissions);
webBrowser.Navigated += WebBrowserNavigated;
webBrowser.Navigate(destinationURL);
}
private void WebBrowserNavigated(object sender, WebBrowserNavigatedEventArgs e)
{
// get token
var url = e.Url.Fragment;
if (url.Contains("access_token") && url.Contains("#"))
{
this.Hide();
url = (new Regex("#")).Replace(url, "?", 1);
this.AccessToken = System.Web.HttpUtility.ParseQueryString(url).Get("access_token");
//MessageBox.Show(facebookCore.AccessToken);
try
{
//var facebooking = new FacebookingTest(facebookCore.AccessToken);
//facebooking.UpdateStatus();
var fb = new FacebookClient(this.AccessToken);
dynamic result = fb.Post("me/feed", new { message = "Hi..Test33" });
var newPostId = result.id;
}
catch (Exception exception)
{
Console.Write(exception);
}
}
}
}
Try opening the file App.Config and modify the last line of the
<appsettings>
section as follows:
<add key="ExtendedPermissions" value="offline_access,publish_stream,publish_actions" />

Categories