This should be very simple, but im notsure what is wrong.
Every time i try and access "http://localhost:50949/api/projects", i get the following error
The requested resource does not support http method 'GET'
WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
ApiController
private const string m_BaseUrl = "http://example.com/rest/api/2/";
private string m_Username = Properties.Settings.Default.username;
private string m_Password = Properties.Settings.Default.password;
// GET: api/Projects
[HttpGet]
public IEnumerable<string> Get(JiraResource resource, string argument = null, string data = null, string method = "GET")
{
string url = string.Format("{0}{1}/", m_BaseUrl, resource.ToString());
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.ContentType = "application/json";
request.Method = method;
string base64Credentials = GetEncodedCredentials();
request.Headers.Add("Authorization", "Basic " + base64Credentials);
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
string result = string.Empty;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
}
return null;
}
private string GetEncodedCredentials()
{
string mergedCredentials = string.Format("{0}:{1}", m_Username, m_Password);
byte[] byteCredentials = UTF8Encoding.UTF8.GetBytes(mergedCredentials);
return Convert.ToBase64String(byteCredentials);
}
HTML/JS
<h2>Projects</h2>
<button id="projects" class="btn btn-info">List Projects</button>
#section scripts
{
<script>
$(document)
.ready(function() {
$("#projects")
.click(function(e) {
var button = $(e.target);
$.get("/api/projects/")
.done(function() {
alert("Got Projects");
})
.fail(function() {
alert("Something failed!");
});
});
});
</script>
}
If i do it through the UI i get "Something Failed"
In your method int the controller you still have to put the route attribute even if it is empty string:
[HttpGet]
[Route("")]
public IEnumerable<string> Get(JiraResource resource, string argument = null, string data = null, string method = "GET")
{
...
}
Related
I am creating an asp.net web service and I want to use an HTML page with son content to be passed to it. I have the json data in the controller but when I return, I want to specify which view to sealing with the json data.
[HttpPost]
public async Task<IActionResult> Create(IFormFile postedFile)
{
byte[] data;
using (var br = new BinaryReader(postedFile.OpenReadStream()))
{
data = br.ReadBytes((int)postedFile.OpenReadStream().Length);
}
HttpContent fileContent = new ByteArrayContent(data);
string uirWebAPI = _configuration.GetValue<string>("Api");
using (var client = new HttpClient())
{
using (var formData = new MultipartFormDataContent())
{
formData.Add(fileContent, "file", "File");
client.DefaultRequestHeaders.Add("blobPath", meshFilePath);
// calling another API to do some processing and return a json response
var response = client.PostAsync(uirWebAPI, formData).Result;
if (response.IsSuccessStatusCode)
{
using (Stream responseStream = await response.Content.ReadAsStreamAsync())
{
jsonMessage = new StreamReader(responseStream).ReadToEnd();
}
var jsonString = await response.Content.ReadAsStringAsync();
jsonObject = JsonConvert.DeserializeObject<object>(jsonString);
}
else
{
return null;
}
}
}
ViewData["jsonData"] = jsonString;
return View();
}
I want to do something like:
var jsonData = jsonObject
return View("myHTMLpage", jsonData);
How to do it with ASP.NET MVC ?
You can create custom ActionResult as JsonNetResult
public class JsonNetResult : ActionResult
{
public Encoding ContentEncoding { get; set; }
public string ContentType { get; set; }
public object Data { get; set; }
public JsonSerializerSettings SerializerSettings { get; set; }
public Formatting Formatting { get; set; }
public JsonNetResult() {
SerializerSettings = new JsonSerializerSettings();
}
public override void ExecuteResult( ControllerContext context ) {
if ( context == null )
throw new ArgumentNullException( "context" );
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = !string.IsNullOrEmpty( ContentType )
? ContentType
: "application/json";
if ( ContentEncoding != null )
response.ContentEncoding = ContentEncoding;
if ( Data != null ) {
JsonTextWriter writer = new JsonTextWriter( response.Output ) { Formatting = Formatting };
JsonSerializer serializer = JsonSerializer.Create( SerializerSettings );
serializer.Serialize( writer, Data );
writer.Flush();
}
}
}
The httpPost transfer with parameters fails in the apiconroller.
It is trying to communicate from Android to Web server.
I succeeded in communicating with Get and Post, which had no parameters.
However, if parameter is added in Post transmission, it fails. I certainly think there is a problem with the Web server code.
The tutorial only contains information about the Model. I want to exchange strings.
Global.asax.cs
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
//....
}
WebApiConfig.cs
public class WebApiConfig
{
public const string UrlPrefix = "api";
public const string UrlPrefixRelative = "~/" + UrlPrefix;
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
var httpControllerRouteHandler = typeof(HttpControllerRouteHandler).GetField("_instance",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
if (httpControllerRouteHandler != null)
{
httpControllerRouteHandler.SetValue(null,
new Lazy<HttpControllerRouteHandler>(() => new SessionHttpControllerRouteHandler(), true));
}
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: UrlPrefix + "/{controller}/{action}/{sn}",
defaults: new { action = "Index", sn = RouteParameter.Optional }
);
}
public class SessionControllerHandler : HttpControllerHandler, IRequiresSessionState
{
public SessionControllerHandler(RouteData routeData) : base(routeData) { }
}
public class SessionHttpControllerRouteHandler : HttpControllerRouteHandler
{
protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
=> new SessionControllerHandler(requestContext.RouteData);
}
}
ApiController.cs
public class LicenseController : ApiController
{
[HttpPost]
public HttpResponseMessage GetLicense([FromBody]string data)
{
return Request.CreateResponse(HttpStatusCode.OK, data);
}
[HttpGet]
public HttpResponseMessage GetLicense2(string data)
{
string udid = data;
string license = AES.Encrypt(udid);
return Request.CreateResponse(HttpStatusCode.OK, license);
}
[HttpPost]
public HttpResponseMessage GetLicense3()
{
return Request.CreateResponse(HttpStatusCode.OK, "ABC");
}
}
android code
new Thread(new Runnable() {
#Override
public void run() {
try{
// Defined URL where to send data
URL url = new URL("http://192.1.1.1:80/api/License/GetLicense/");
// Send POST data request
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
//wr.write(URLEncoder.encode("data=3434", "UTF-8") );
wr.write("data=3434");
wr.flush();
// Get the server response
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
// Read Server Response
while((line = reader.readLine()) != null)
{
// Append server response in string
sb.append(line + "\n");
}
}
catch(Exception ex)
{
}
}
}).start();
For a web api POST method accepting a single string parameter you can do:
[HttpPost]
public HttpResponseMessage GetLicense([FromBody]string data)
And then post the data from client like:
wr.write("=3434");
For multiple post parameters, create a model class in Web API:
public class DataModel {
public string data1 {get;set;}
public string data2 {get;set;}
}
Update api endpoint parameter type:
[HttpPost]
public HttpResponseMessage GetLicense([FromBody]DataModel dataModel)
Then post json string from client with content-type: "application/json"
{
"data1": "Data1 contents",
"data2": "Data2 contents"
}
I am using ASP.NET Web API and I want to send a list of objects as a JSON array but keep receiving
"The remote server returned an error: (400) Bad Request."
When I send a single object it works fine.
Here's my code:
"Server" Side Code:
public class Trigger
{
public string TriggerID { get; set; }[Required]
public string TriggerName { get; set; }[Required]
public string TriggerDescription { get; set; }
}
public class TriggersController : Controller
{
[HttpPost]
public HttpResponseMessage AddTriggers(IQueryable<Trigger> TriggerEvent)
{
if (SetUserDetails())
{
if (ModelState.IsValid)
{
return _repository.AddTriggers(TriggerEvent);
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
else
{
throw new HttpResponseException(new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized) { Content = new StringContent("Incorrect token") });
}
}
}
"Client" side Code:
string JSON = [{"TriggerID":"1","TriggerName":"My 1 Event","TriggerDescription":"This is my 1 event"},{"TriggerID":"2","TriggerName":"My 2 Event","TriggerDescription":"This is my 2 event"}]
public string AddTrigger(string URL, string JSON)
{
string ret = string.Empty;
StreamWriter requestWriter;
var webRequest = System.Net.WebRequest.Create(URL) as HttpWebRequest;
if (webRequest != null)
{
webRequest.Headers.Add("Authorization-Token", AuthenticationCode);
webRequest.Method = "POST";
webRequest.ContentType = "application/json";
//POST the data.
using (requestWriter = new StreamWriter(webRequest.GetRequestStream()))
{
requestWriter.Write(JSON);
}
}
HttpWebResponse resp = (HttpWebResponse)webRequest.GetResponse();
Stream resStream = resp.GetResponseStream();
StreamReader reader = new StreamReader(resStream);
ret = reader.ReadToEnd();
return ret;
}
OK, found my mistake, should use IEnumerable instead of IQueryable and everything works fine.
I just Register these routes now how can I get Apikey value in WebApiKeyHandler.cs since it is not part of query string so I am getting null. Also guide me how I am validating keys is best practice for Web Api Project?
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi2",
routeTemplate: "api/v1/users/{apikey}/{controller}/{action}/",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/v1/users/{apikey}/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.MessageHandlers.Add(new WebApiKeyHandler()); // global message handler
}
WebApiKeyHandler.cs
public class WebApiKeyHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
string apikey = HttpUtility.ParseQueryString(request.RequestUri.Query).Get(Constants.API_KEY_QUERY_STRING);
if (string.IsNullOrWhiteSpace(apikey))
{
HttpResponseMessage response = request.CreateErrorResponse(HttpStatusCode.Forbidden, ErrorCodes.API_KEY_EMPTY_ERROR);
var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(response);
return tsc.Task;
}
else if (!ValidateKey(apikey))
{
HttpResponseMessage response = request.CreateErrorResponse(HttpStatusCode.Forbidden, ErrorCodes.API_KEY_INVALID_ERROR);
var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(response);
return tsc.Task;
}
else
{
return base.SendAsync(request, cancellationToken);
}
}
private static bool ValidateKey(string apiKey)
{
Guid key;
Guid.TryParse(apiKey, out key);
return new StAccountsDomainContext().ApiSubscriptions.Any(x => x.ApiKey == key && x.IsActive == true && !x.ApiIBlacklists.Any());
}
private static bool ValidateSecretKey(string apiKey, string secretKey)
{
Guid key1;
Guid.TryParse(apiKey, out key1);
Guid key2;
Guid.TryParse(secretKey, out key2);
return new StAccountsDomainContext().ApiSubscriptions.Any(x => x.ApiKey == key1
&& x.SecretKey == key2
&& x.IsActive == true
&& !x.ApiIBlacklists.Any());
}
}
You can use the GetRouteData() extension on HttpRequestMessage to get the route data. Example: request.GetRouteData().Values
I have this common CUser class
public class CUser
{
public String Username { get; set; }
public String Password { get; set; }
}
Then I have this code on my client that uses RestSharp
public void CreateUser()
{
RestRequest request = new RestRequest(Method.POST);
request.RequestFormat = DataFormat.Json;
request.Resource = "user/{cUser}";
CUser user = new CUser
{
Username = "Foo",
Password = "BarBaz"
};
request.AddParameter("cUser", user, ParameterType.UrlSegment);
client.PostAsync<int>(request, (response, handler) =>
{
System.Diagnostics.Debug.WriteLine(response.StatusDescription);
System.Diagnostics.Debug.WriteLine("id: " + response.Data);
});
}
And this http route in my global.asax
routes.MapHttpRoute(
name: "CreateUser",
routeTemplate: "api/{controller}/{cUser}",
defaults: new
{
controller = "User",
action = "CreateUser",
cUser = RouteParameter.Optional
});
And this servercode to handle it
public int CreateUser(CUser cUser)
{
User user = new User(cUser);
LoginManager manager = new LoginManager();
return manager.CreateUser(user);
}
But everytime I run it cUser's values are null (Username and Password) so do I need to do something to restsharp to make it serialize it properly?
I think this is what you want:
request.AddParameter("username", user.Username);
request.AddParameter("password", user.Password);
What you're doing would result in cUser.ToString() being substituted for the {cUser} placeholder.