WebService(WebApi) and Console C# to access it, getting error 500 - c#

I'm trying to create a web api to send data to a database and receive other info. My web api will be in the center of 2 different application that i doesn't own!
But when I try to reach my WebApi from a console application, I'm always getting the
"(500) Internal Server Error."
So here is my code and my class (At the moment I'm practicing in a fake project to get experience)
BTW I use .Net 4 (not 4.5)
Everything is in a Big project and separated with solution that I will say with each class
Solution : DataModel
Class : Permission
public class Permission
{
public int PermissionId { get; set; }
[MaxLength(50)]
public string Type { get; set; }
}
Solution : WebService
Class : PermissionController : ApiController
public class PermissionController : ApiController
{
[HttpGet]
public object Get([FromUri] int id)
{
Permission permission = PermissionDal.GetPermissionById(id);
if (permission == null)
{
return new { Success = Dal.Error };
}
return new { Success = Dal.Done, Permission = permission };
}
}
Solution : DataAccess
Class : PermissionDal
public static class PermissionDal
{
public static Permission GetPermissionById(int id)
{
return (from p in db.DbPermission where p.PermissionId == id select p).FirstOrDefault();
}
}
Solution : Console
Class : Program
static void Main(string[] args)
{
using (var client = new WebClient())
{
client.Headers.Clear();
client.Headers.Add("content-type", "application/json");
string result = client.DownloadString("http://localhost:50171/api/Permission?id=1");
Console.WriteLine(result);
}
}
My webservice solution is really running on port 50171 from the visual studio properties of the project WebService.
I tried
string result = client.DownloadString("http://localhost:50171/api/Permission/1");
I tried
string result = client.DownloadString("http://localhost:50171/api/permission?id=1");
I tried
string result = client.DownloadString("http://localhost:50171/api/permission/1");
I'm always getting the same error.

Related

HttpResponseMessage post API json format with C#

I used the HttpResponseMessage Post method to let the mobile terminal verify the account password. I used the following CODE to run successfully, but the POST format must be run like this.
'{"ID":"xxx","Password":"xxx"}'
It need two ' can run, I don't know why.
I can't request a service using the normal POST format on iOS or Android.
The format I want is {"ID":"xxx","Password":"xxx"},without '
[HttpPost]
public HttpResponseMessage Post([FromBody] string DATA)
{
using (appapidataEntities entities = new appapidataEntities())
{
//string controllerName = ControllerContext.RouteData.Values["controller"].ToString();
JObject jo = JObject.Parse(DATA);
string id = jo["ID"].ToString();
string password = jo["Password"].ToString();
var user = entities.USERs.Where(x => x.ID == id && x.Password == password).FirstOrDefault();
var result = new
{
message = "failure"
};
var result2 = new
{
message = "success"
};
if (user == null)
{
return Request.CreateResponse(HttpStatusCode.OK, result);
}
else
{
return Request.CreateResponse(HttpStatusCode.OK, result2);
}
}
}
public partial class USER
{
public string ID { get; set; }
public string Password { get; set; }
}
}
Please have someone with experience to help me, thank you very much.
As #Nkosi said, the correct way to receive a complex object is using a class/object (also called 'model binding')
In your models add this class. This class will be the 'contract' between the service with any external application who calls the service. Usually, any client (service, app or frontend) also has a class with this contract to call the service.
public class LoginViewModel {
public string ID { get; set; }
public string Password { get; set; }
}
Now, modify the controller as follow
[HttpPost]
public HttpResponseMessage Post([FromBody] LoginViewModel DATA) {
using (appapidataEntities entities = new appapidataEntities())
string id = DATA.ID;
string password = DATA.Password;
// rest of the code
}
}
Make sure the device is sending the data the service is waiting (maybe adding a breakpoint if you are debugging from Android Studio before to make the request) and add a breakpoint in your controller to verify that the variable DATA has the correct values.

HttpClient.PostAsync return System.IO.Stream as property

I have some legacy code that I'm trying to work with and need to return an existing object that contains a Stream from an ApiController
public class LegacyObject
{
public bool Result { get; set; }
public Stream Stream { get; set; }
}
API Code
public class BindJson : System.Web.Http.Filters.ActionFilterAttribute
{
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
string rawRequest;
using (var stream = new StreamReader(actionContext.Request.Content.ReadAsStreamAsync().Result))
{
stream.BaseStream.Position = 0;
rawRequest = stream.ReadToEnd();
}
rawRequest = rawRequest.ToString();
var obj = JsonConvert.DeserializeObject<LegacyParameters>(rawRequest.ToString());
actionContext.ActionArguments["parameter"] = obj;
}
}
public class ReportsController : ApiController
{
[BindJson]
[HttpPost]
public LegacyObject ReturnReport([FromBody]LegacyParameters parameter)
{
LegacyObject r = LegacyClass.GetReportStream(parameters);
return r; //Object properties are correctly set and no errors at this point
}
}
My call to the Api is
using (var httpClient = new System.Net.Http.HttpClient())
{
httpClient.BaseAddress = new Uri("http://myserver/");
string contents = JsonConvert.SerializeObject(paramList);
var response = httpClient.PostAsync("/api/ReturnReport", new StringContent(contents, Encoding.UTF8, "application/json")).Result;
}
I get a 500 Internal Server Error on the PostAsync when my LegacyObject.Stream has content. It works when the stream content is null. I'm working locally on my development PC and web server for the API is IIS Express.
Any advice would be appreciated.
So in order to get more detail on the 500 Internal Server Error, I added this to my projects WebApiConfig Register
config.Services.Replace(typeof(IExceptionLogger), new UnhandledExceptionLogger());
With this class
public class UnhandledExceptionLogger : ExceptionLogger
{
public override void Log(ExceptionLoggerContext context)
{
var log = context.Exception.ToString();
//Write the exception to your logs
}
}
The log variable now gives me the detail I need to debug
FYI - The error was a read timeout on my Stream

How Many Delete or Put methods in a WebApi Controller?

I have a problem with ASP.NET WebAPI`. I wanted to keep in RESTful API, so I create some apis in one controller, such as:
GET /api/user/ - userslist
GET /api/user/{id} - a user
GET /api/user/{id}/books - get all books of the user
Delete /api/user/{id} - delete the user
Delete /api/user/{id}/books - delete users' books
All the Get methods works fine, but only one Delete method can work, when the other was called, it will got a 405 response. Could you help me ?
Thanks. here is my controller
[RoutePrefix("api/Car")]//AttributeRouting asp.net 4.0 (not 5.0)
public class CarController : ApiController
{
public CarInfoPagedList GetCarInfos(int page = 0, int limit = 10)
{
var list = new CarInfoPagedList();
return list;
}
[HttpRoute("{id}")]
public string GetCarById(string id, string time = " ")
{
return "some";
}
[HttpRoute("{id}/runtime")]
public CarState GetCarRuntime(string id) {
return new CarState(id);
}
[DELETE("{id}")]//405
public void DeleteCar(string id)
{
//TODO:remove car
}
[DELETE("{id}/terminal/{terminalId}")]//work fine
public void Delete(string id, string terminalId)
{
}
[PUT("{id}/")]//405
public void PutCar(string id, CarInfo car)
{
}
[PUT("{id}/terminal/{terminalId}")]//work fine
public void Put(string id, string terminalID)
{
}
}

How To Call Servicestack service deployed on remote server from MVC4.net application deployed on another server?

I am new to Servicestack and trying to implement it for my current project.Now I have my MVC.NET application deployed on one server
(say http://server1:8080) and servicestack service deployed on different one (say http://server2:9080).
I have already gone through
https://github.com/ServiceStack/ServiceStack/wiki/Mvc-integration
but i am not able to understand how to change that to call service from http://server2:9080
how to call service from my MVC controller?
Service code is as following
// APPHOST.cs
public class AppHost : AppHostBase
{
public AppHost() : base("Flight app host",
typeof(flightService).Assembly) { }
public override void Configure(Container container)
{
}
}
// Request DTO
[Route("/flights/","POST")]
[Route("/flights/{departure}/{arrival}","POST")]
public class TravelServiceRequest : IReturn<TravelServiceResponce>
{
public string departure { get; set; }
public string arrival { get; set; }
}
// Response DTO
public class TravelServiceResponce
{
public string departure { get; set; }
public string arrival { get; set; }
public string airline { get; set; }
public decimal fare { get; set; }
public DateTime arrivalTime { get; set; }
public DateTime departureTime { get; set; }
}
// service
public class flightService:Service
{
public object Post(TravelServiceRequest request)
{
var response = new TravelServiceResponce
{
departure =request.departure,
arrival =request.arrival,
airline="jet airways",
fare =677,
arrivalTime =new DateTime(2014,12,12,5,6,2),
departureTime = new DateTime(2014,11,12,5,6,2)
};
return response;
}
}
// Gloable.asax.cs file
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
var appHost = new AppHost();
appHost.Init();
}
}
In my MVC apllication
public class HomeController : Controller
{
public ActionResult Index()
{
//call service from here
return View();
}
}
I have c# code to call this service but i am not sure if this is the best way to use in MVC controller
var client = new JsonServiceClient("http://server2:9080/");
var responce = client.Post(new TravelServiceRequest
{
departure = departure,
arrival = arrival
});
Please help me with best way to call remote service in MVC.
Calling ServiceStack Services out-of-process
If ServiceStack and MVC are not hosted together in the same Web Application then you would just access the ServiceStack Service as you would from any .NET Service Client using the ServiceStack Server DTO's and a .NET Service Client, e.g:
var response = client.Post(new TravelServiceRequest { ... });
Another alternative to sharing the Server DTO .dll is to use the VS.NET Integration offered by Add ServiceStack Reference which lets you generate Server DTO's from a remote url.
ServiceStack + MVC In Process
If ServiceStack and MVC are hosted together in the same AppDomain refer to the ServiceStack Integration with MVC which allow your Controllers can access most of ServiceStack functionality by inheriting from ServiceStackController.
You can then Execute a ServiceStack Service in-process in your MVC Controllers with:
var response = base.Execute(new TravelServiceRequest { ... });
This is equivalent to resolving the ServiceStack Service from the IOC and calling it directly which you can do instead, e.g:
using (var service = base.ResolveService<TravelServices>())
{
var response = service.Post(new TravelServiceRequest { ... });
}

Review my ASP.NET Authentication code

I have had some problems with authentication in ASP.NET. I'm not used most of the built in authentication in .NET.
I gotten some complaints from users using Internet Explorer (any version - may affect other browsers as well) that the login process proceeds but when redirected they aren't authenticated and are bounced back to loginpage (pages that require authentication check if logged in and if not redirect back to loginpage). Can this be a cookie problem?
Do I need to check if cookies are enabled by the user?
What's the best way to build authentication if you have a custom member table and don't want to use ASP.NET login controls?
Here my current code:
using System;
using System.Linq;
using MyCompany;
using System.Web;
using System.Web.Security;
using MyCompany.DAL;
using MyCompany.Globalization;
using MyCompany.DAL.Logs;
using MyCompany.Logging;
namespace MyCompany
{
public class Auth
{
public class AuthException : Exception
{
public int StatusCode = 0;
public AuthException(string message, int statusCode) : base(message) { StatusCode = statusCode; }
}
public class EmptyEmailException : AuthException
{
public EmptyEmailException() : base(Language.RES_ERROR_LOGIN_CLIENT_EMPTY_EMAIL, 6) { }
}
public class EmptyPasswordException : AuthException
{
public EmptyPasswordException() : base(Language.RES_ERROR_LOGIN_CLIENT_EMPTY_PASSWORD, 7) { }
}
public class WrongEmailException : AuthException
{
public WrongEmailException() : base(Language.RES_ERROR_LOGIN_CLIENT_WRONG_EMAIL, 2) { }
}
public class WrongPasswordException : AuthException
{
public WrongPasswordException() : base(Language.RES_ERROR_LOGIN_CLIENT_WRONG_PASSWORD, 3) { }
}
public class InactiveAccountException : AuthException
{
public InactiveAccountException() : base(Language.RES_ERROR_LOGIN_CLIENT_INACTIVE_ACCOUNT, 5) { }
}
public class EmailNotValidatedException : AuthException
{
public EmailNotValidatedException() : base(Language.RES_ERROR_LOGIN_CLIENT_EMAIL_NOT_VALIDATED, 4) { }
}
private readonly string CLIENT_KEY = "9A751E0D-816F-4A92-9185-559D38661F77";
private readonly string CLIENT_USER_KEY = "0CE2F700-1375-4B0F-8400-06A01CED2658";
public Client Client
{
get
{
if(!IsAuthenticated) return null;
if(HttpContext.Current.Items[CLIENT_KEY]==null)
{
HttpContext.Current.Items[CLIENT_KEY] = ClientMethods.Get<Client>((Guid)ClientId);
}
return (Client)HttpContext.Current.Items[CLIENT_KEY];
}
}
public ClientUser ClientUser
{
get
{
if (!IsAuthenticated) return null;
if (HttpContext.Current.Items[CLIENT_USER_KEY] == null)
{
HttpContext.Current.Items[CLIENT_USER_KEY] = ClientUserMethods.GetByClientId((Guid)ClientId);
}
return (ClientUser)HttpContext.Current.Items[CLIENT_USER_KEY];
}
}
public Boolean IsAuthenticated { get; set; }
public Guid? ClientId {
get
{
if (!IsAuthenticated) return null;
return (Guid)HttpContext.Current.Session["ClientId"];
}
}
public Guid? ClientUserId {
get {
if (!IsAuthenticated) return null;
return ClientUser.Id;
}
}
public int ClientTypeId {
get {
if (!IsAuthenticated) return 0;
return Client.ClientTypeId;
}
}
public Auth()
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
IsAuthenticated = true;
}
}
public void RequireClientOfType(params int[] types)
{
if (!(IsAuthenticated && types.Contains(ClientTypeId)))
{
HttpContext.Current.Response.Redirect((new UrlFactory(false)).GetHomeUrl(), true);
}
}
public void Logout()
{
Logout(true);
}
public void Logout(Boolean redirect)
{
FormsAuthentication.SignOut();
IsAuthenticated = false;
HttpContext.Current.Session["ClientId"] = null;
HttpContext.Current.Items[CLIENT_KEY] = null;
HttpContext.Current.Items[CLIENT_USER_KEY] = null;
if(redirect) HttpContext.Current.Response.Redirect((new UrlFactory(false)).GetHomeUrl(), true);
}
public void Login(string email, string password, bool autoLogin)
{
Logout(false);
email = email.Trim().ToLower();
password = password.Trim();
int status = 1;
LoginAttemptLog log = new LoginAttemptLog { AutoLogin = autoLogin, Email = email, Password = password };
try
{
if (string.IsNullOrEmpty(email)) throw new EmptyEmailException();
if (string.IsNullOrEmpty(password)) throw new EmptyPasswordException();
ClientUser clientUser = ClientUserMethods.GetByEmailExcludingProspects(email);
if (clientUser == null) throw new WrongEmailException();
if (!clientUser.Password.Equals(password)) throw new WrongPasswordException();
Client client = clientUser.Client;
if (!(bool)client.PreRegCheck) throw new EmailNotValidatedException();
if (!(bool)client.Active || client.DeleteFlag.Equals("y")) throw new InactiveAccountException();
FormsAuthentication.SetAuthCookie(client.Id.ToString(), true);
HttpContext.Current.Session["ClientId"] = client.Id;
log.KeyId = client.Id;
log.KeyEntityId = ClientMethods.GetEntityId(client.ClientTypeId);
}
catch (AuthException ax)
{
status = ax.StatusCode;
log.Success = status == 1;
log.Status = status;
}
finally
{
LogRecorder.Record(log);
}
}
}
}
A classic case of over-engineered Authentication mechanism and on top of it the design is bad.
Exceptions should be out of Auth class but reside in same namespace. Can you imagine how .Net framework would look if Microsoft had created exceptions like this. Always keep it simple, stupid (KISS). It seems you need modular code. Try to be simple yet modular.
Your authentication Client-Keys are static magic-values and you're shipping them with your assemblies. Use SecureString instead of readonly string. Anybody can get hold of it using Reflector. How do you sustain change ad security?
Your code directly refers Current HttpContext object when in fact you could have passed the reference of current context object in client-code that will use this.
RequireClientOfType is int[] - why in the world you want to do this ? I believe it could have been an enum or an immutable struct if at all ever needed.
You are already using FormsAuthentication in your Login() and Logout() which is sufficient to replace your entire Auth. Why do you want to re-invent the wheel if ultimately you are going to use FormsAuthnetication to take care of Auth.
And yes if you cannot revise this design please use FxCop/StyleCop at least to avoid spaghetti-code.
Also you could make class Auth as static and expose functionalities like FormsAuthentication does. And also rename it from Auth to Authentication.
This is a prime candidate for http://thedailywtf.com/
Try using built-in asp.net Forms Authentication (Membership).
You can learn from these videos:
Link1 and Link2
If you want to customize it watch this video:
Link

Categories