I have the following to post JSON to a C# Web API:
submitForm(data: any): Observable<Response> {
return this.http.post(
'https://localhost:44396/api/PostNewComputer/AddItem/?=', data,
{ headers: new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' }) }).subscribe(data => { return "test"; });
}
And the API controller:
public class PostNewComputerController : ApiController
{
[HttpPost]
public IHttpActionResult AddItem(HttpRequestMessage request)
{
//var dynamicObject = Json.Decode(jsonString);
var jsonString = request.GetQueryNameValuePairs();
string message;
using (SqlConnection con = new SqlConnection("data source = MYSERVER; initial catalog = AssetDB; integrated security = SSPI; persist security info = True; Trusted_Connection = Yes"))
{
using (SqlCommand cmd = new SqlCommand("POST_NEW_COMPUTER", con) { CommandType = CommandType.StoredProcedure })
{
try
{
cmd.Parameters.Add(new SqlParameter("#JSON_TEXT", SqlDbType.NVarChar)).Value = jsonString;
con.Open();
cmd.ExecuteNonQuery();
con.Close();
message = "Item Successfully Added";
}
catch (Exception e)
{
//throw e;
message = e.Message;
}
}
return Ok(message);
}
}
}
I am trying to create a response message from the POST call that is then fed back to the webpage when the user submits the form to show that the post has worked.
However, this current setup doesn't work and I am struggling to solves this.
Is there a correct way to do this properly?
Use HttpResponseMessage to post back message as:
[HttpPost]
[ResponseType(typeof(string))]
public HttpResponseMessage AddItem(HttpRequestMessage request)
{
HttpResponseMessage response = null;
string message = string.Empty;
try
{
.....
message = "Item Successfully Added";
}
catch (Exception e)
{
.....
message = e.Message;
}
response = Request.CreateResponse<string>(HttpStatusCode.OK, message);
return response;
}
The problem is in your Angular service. Your API is correct
You're trying to subscribe to the response from your API before mapping it back to json(), you need to do the following, see below:
Firstly this is what should be in your component:
submitForm(data: any): Observable<Response> {
//this url can't be correct?
let url:string = 'https://localhost:44396/api/PostNewComputer/AddItem/?=';
return this.http.post(url, data, this._headers())
.map((res:Response) => res.json());
}
//Created a method to do the headers for you
private _headers():RequestOptionsArgs {
let headers:Headers = new headers();
headers.append('Content-Type', 'application/json');
let options:RequestOptionsArgs = new RequestOptions();
options.headers = headers;
return options;
}
You would then call your service from your component as follows:
public functionName():void {
this.service.submitForm(data)
.subscribe((res:any) => {
//this will contain your response
},
(error:any) => {
//this will contain your error
});
}
You need to ensure the model you're posting matches the model expected. With regards to the URL you are posting to, that seems incorrect, is it not https://localhost:44396/api/PostNewComputer/AddItem/?
Related
I have a .net core API service which is called from a angular client project.
When a user request a status of his payment, we will make call to this service api and this service will then call a payment gateway service to fetch the status of payment and the output result will return to the user.
When i try to integrate this i am facing this below error.
net::ERR_CONNECTION_RESET 200 (OK)
core.js:5967 ERROR Unknown Error
This above issue is not showing when i try to hit the service after putting one breakpoint. Its also returning the result.
This is how entire flow works
Client side call performs by user
this.dataservice.postFeed(method, JSON.stringify(this.initsearch)).subscribe(result => {
var response = result.body["data"];
console.log(response);
});
Server side code looks like
[HttpPost]
public async Task<IActionResult> Post([FromBody] ObjectModel searchValue)
{
ApiResponse<string> response = new ApiResponse<string>();
IBaseResult<string> result = await _adlerBo.GetPaymentStatus(searchValue);
response.Success = result.success;
response.Data = result.Data;
return Ok(response);
}
In BusinessObject.cs
public async Task<IBaseResult<string>> GetPaymentStatus(PaymentSearchModel requestModel){
string apiResponse = await PaymentStatusCheckUsingAPI(requestModel.orderid);
return apiResponse ;
}
private async Task<string> PaymentStatusCheckUsingAPI(string orderNumber)
{
string message = await PostPaymentRequestToGateway(statusApiUrl, authQueryUrlParam);
NameValueCollection param = await GetResponseMap(message);
string status = "";
string encResJson = "";
if (param != null && param.Count == 2)
{
for (int i = 0; i < param.Count; i++)
{
if ("status".Equals(param.Keys[i]))
{
status = param[i];
}
if ("enc_response".Equals(param.Keys[i]))
{
encResJson = param[i];
}
}
if (!"".Equals(status) && status.Equals("0"))
{
resJson = crypto.Decrypt(encResJson, workingKey);
}
else if (!"".Equals(status) && status.Equals("1"))
{
Console.WriteLine("failure response: " + encResJson);
}
}
return resJson;
}
private async Task<string> PostPaymentRequestToGateway(string queryUrl, string urlParam)
{
string message = "";
try
{
StreamWriter myWriter = null;// it will open a http connection with provided url
WebRequest objRequest = WebRequest.Create(queryUrl);//send data using objxmlhttp object
objRequest.Method = "POST";
//objRequest.ContentLength = TranRequest.Length;
objRequest.ContentType = "application/x-www-form-urlencoded";//to set content type
myWriter = new System.IO.StreamWriter(objRequest.GetRequestStream());
myWriter.Write(urlParam);//send data
myWriter.Close();//closed the myWriter object
// Getting Response
System.Net.HttpWebResponse objResponse = (System.Net.HttpWebResponse)objRequest.GetResponse();//receive the responce from objxmlhttp object
using (System.IO.StreamReader sr = new System.IO.StreamReader(objResponse.GetResponseStream()))
{
message = await sr.ReadToEndAsync();
//Response.Write(message);
}
}
catch (Exception exception)
{
Console.Write("Exception occured while connection." + exception);
}
return message;
}
private async Task<NameValueCollection> GetResponseMap(string message)
{
//await Task.Delay(2000); I did this with no Luck
NameValueCollection Params = new NameValueCollection();
if (message != null || !"".Equals(message))
{
string[] segments = message.Split('&');
foreach (string seg in segments)
{
string[] parts = seg.Split('=');
if (parts.Length > 0)
{
string Key = parts[0].Trim();
string Value = parts[1].Trim();
Params.Add(Key, Value);
}
}
}
return await Task.FromResult(Params);
}
Any idea how to fix this? Why its working when i put breakpoint and not otherwise.
Am i doing correct asynchronous implimentsion in my api?
I am sending token in metadata from the client side
Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure);
ItemQuery item = new ItemQuery() { Id = "abc" };
var client = new MyService.MyServiceClient(channel);
Metadata data = new Metadata
{
{ "token", "Bearer xhrttt" }
};
var reply = client.GetItem(item, data);
But not able to find a way to fetch it in server side, Any help is appreciated
below is an example of how my server-side code looks(i tried certain other ways also)
public override Task<ItemResponse> GetItem(ItemQuery request , ServerCallContext context)
{
try
{
var a = context.RequestHeaders["token"]; // not working
ItemResponse itmRes = new ItemResponse();
if (request.Id == "foo")
{
itmRes.Items.Add(new Item() { Id = "foo", Name = "foobar" });
}
return Task.FromResult(itmRes);
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
return null;
}
Below is the code to fetch metadata in c#
Metadata.Entry metadataEntry = context.RequestHeaders.FirstOrDefault(m =>
String.Equals(m.Key, "token", StringComparison.Ordinal));
if (metadataEntry.Equals(default(Metadata.Entry)) || metadataEntry.Value == null)
{
return null;
}
Console.WriteLine("Token value is {0}", metadataEntry.Value);
for more details refer https://csharp.hotexamples.com/examples/Grpc.Core/ServerCallContext/-/php-servercallcontext-class-examples.html
Based on this tutorial, this and this, getting and setting metadata can be summarized:
GreeterService.cs (GrpcGreeter.csproj)
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
context.WriteResponseHeadersAsync(
new Metadata() { { "server_header", "nice to see you too" } });
context.ResponseTrailers.Add(
new Metadata.Entry("server_trailer", "see you later") { });
string? client_header = context.RequestHeaders.GetValue("client_header");
return Task.FromResult(new HelloReply
{
Message = $"i got your header, {request.Name}. it reads: {client_header}"
});
}
Program.cs (GrpcGreeterClient.csproj)
// The port number must match the port of the gRPC server.
using var channel = GrpcChannel.ForAddress("https://localhost:7143");
Greeter.GreeterClient client = new Greeter.GreeterClient(channel);
var call = client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" },
new Metadata() { { "client_header", "hey there" } });
Metadata headers = await call.ResponseHeadersAsync;
Console.WriteLine($"Server Header: {headers.GetValue("server_header")}");
HelloReply rsp = await call.ResponseAsync;
Console.WriteLine($"Server Response: {rsp.Message}");
Metadata trailers = call.GetTrailers();
string? myTrailer = trailers.GetValue("server_trailer");
Console.WriteLine($"Server Trailers: {myTrailer}");
Output:
Server Header: nice to see you too
Server Response: i got your header, GreeterClient. it reads: hey there
Server Trailers: see you later
I am new to web api. I have a method, that returns 3 objects from response message. I want to get specific object from the response message,
public HttpResponseMessage GetAllStudents(HttpReqestMessage request)
{
HttpResponseMessage response = null;
return CreateHttpResponse(request, () =>
{
// some logics here
response = request.CreateResponse(HttpStatusCode = OK, new {success = true, StudentName, ListOfStudents, ListOfSubjects});
return response;
});
}
In this above code i want to get the ListOfStudents object alone from the response message. Please anyone help me to get this.
I think you have a malformatted json , you should create a property for each list, check the next example :
public HttpResponseMessage GetAllStudents(HttpReqestMessage request)
{
HttpResponseMessage response = null;
return CreateHttpResponse(request, () =>
{
// some logics here
response = request.CreateResponse(HttpStatusCode = OK, new {success = true, studentName = StudentName, listOfStudents = ListOfStudents, listOfSubjects = ListOfSubjects});
return response;
});
}
Example getting this with with jquery
$.get("GetAllStudents", function(data) {
if (data.success)
{
console.log(data.listOfStudents);
}
});
I am currently working on a Xamarin Studio Forms application where I both get and post data with REST-api calls. I do this with both messaging and also by storing login credentials. With my current frontend C# and backend PHP setup I can successfully login users, but now i wish to add security to the whole thing.
Right now to see if a your user credentials are correct I do this:
static public async Task<JObject> LoginUser(string Email, string Password)
{
var httpClientRequest = new HttpClient();
try
{
var result = await httpClientRequest.GetAsync(”http://myURL.com/Signingup/Login.php?Email=" + Email + "&Password=" + Password);
var resultString = await result.Content.ReadAsStringAsync();
var jsonResult = JObject.Parse(resultString);
return jsonResult;
}
catch {
return null;
}
}
And I retrieve it with this PHP code:
<?php
class ConnectionInfo
{
public $conn;
public function GetConnection() {
$this->conn = mysqli_connect(”server”, ”user”,”pass”, ”db”) or die(mysqli_error($mysql_pekare));
}
}
$connectionInfo = new ConnectionInfo();
$connectionInfo->GetConnection();
if (!$connectionInfo->conn)
{
echo 'No Connection';
}
else
{
$Email = $_GET['Email'];
$Password = $_GET['Password'];
$query = "SELECT * FROM Login WHERE Email = '$Email' AND Password = '$Password'";
$stmt = mysqli_query($connectionInfo->conn, $query);
if (!$stmt)
{
echo 'Query failed';
}
else
{
$contacts = array();
while ($result = mysqli_fetch_array($stmt))
{
$contact = array("Email" => utf8_encode ($result['Email']),"Password" => utf8_encode ($result['Password']),
"UserID" => ($result['UserID']));
array_push($contacts, $contact);
}
echo json_encode ($contact, JSON_PRETTY_PRINT);
}
}
?>
This works and I can successfully retrieve the data in my C# application and successfully login a user. But now the security aspects comes in. How would I secure this?
I read briefly about ”hashing” but also about creating ”sessiontokens” but I am unsure on which way to go/which way would be the best and most secure approach.
When I looked at an old example with ”Parse” I saw that they added a App-ID key and a REST Api key with all their httpClientRequest calls, looking like this:
httpClientRequest.DefaultRequestHeaders.Add ("X-Parse-Application-Id", appIdString);
httpClientRequest.DefaultRequestHeaders.Add ("X-Parse-REST-API-Key", apiKeyString);
Could this be a good way to approach it? If it is and I add these headers to my GetAsync call, what would I then need to do with my PHP code in order to retrieve the call?
This is the signup code:
C#
static public async Task<JObject> SignupUser(string Email, string Password)
{
var httpClientRequest = new HttpClient();
var postData = new Dictionary<string, object>();
try
{
postData.Add("Email", Email);
postData.Add("Password", Password);
var jsonRequest = JsonConvert.SerializeObject(postData);
HttpContent content = new StringContent(jsonRequest, System.Text.Encoding.UTF8, "application/json");
var result = await httpClientRequest.PostAsync("http://url.com/Signup/Signup.php", content);
var resultString = await result.Content.ReadAsStringAsync();
var jsonResult = JObject.Parse(resultString);
return jsonResult;
}
catch {
return null;
}
}
PHP:
<?php
$value = json_decode(file_get_contents('php://input'));
$mysql_pekare= new mysqli ("serv", "user","pass", "db");
if(!empty($value)) {
$stmt = $mysql_pekare->prepare("INSERT INTO Login (`Email`, `Password`) VALUES(?,?)");
$stmt->bind_param("ss", $value->Email, $value->Password);
printf(mysqli_insert_id());
$stmt->execute();
if(!empty($stmt)) {
session_start();
$contacts = array();
$id = mysqli_insert_id();
$contact = array("UserID" => ($stmt->insert_id));
array_push($contacts, $contact);
echo json_encode ($contact, JSON_PRETTY_PRINT);
$stmt->close();
$mysql_pekare->close();
}
}
}
?>
I am using the default Web Api controller that is auto generated. I am testing the validation and error handling in the client side. But somehow I have realised that the detail error message is not passed to client. Either if I throw HttpResponseException or returning IHttpActionResult in both cases the client is seeing only "Bad Request" but not the detailed message. Can anyone explain what is going wrong please?
public IHttpActionResult Delete(int id)
{
if (id <= 0)
{
var response = new HttpResponseMessage(HttpStatusCode.NotFound)
{
Content = new StringContent("Id should be greater than zero.", System.Text.Encoding.UTF8, "text/plain"),
StatusCode = HttpStatusCode.NotFound
};
throw new HttpResponseException(response) // Either this way
}
var itemToDelete = (from i in Values
where i.Id == id
select i).SingleOrDefault();
if (itemToDelete == null)
{
return BadRequest(string.Format("Unable to find a value for the Id {0}", id)); // Or This way
}
Values.Remove(itemToDelete);
return Ok();
}
client code is as:
private async static Task DeleteValue(int id)
{
var url = "http://localhost:13628/api/Values/" + id;
using (var client = new HttpClient())
{
var response = await client.DeleteAsync(url);
if (response.IsSuccessStatusCode)
{
await ReadValues();
}
else
{
Console.WriteLine(response.ReasonPhrase);
Console.WriteLine(response.StatusCode);
}
}
}
None of the above works??
Thx
In your client side change Console.WriteLine(response.ReasonPhrase);
to Console.WriteLine(response.Content.ReadAsStringAsync().Result);
and it will give the detailed error message.
Replace below code into Web API delete action. Use HttpResponseMessage as return tpye for api instead of IHttpActionResult
[HttpDelete]
[Route("{id:int:min(1)}")]
public async Task<HttpResponseMessage> DeleteAsync(int id)
{
if(id < 0 )
{
return await Task.FromResult<HttpResponseMessage>(Request.CreateResponse<string>(HttpStatusCode.BadRequest, "Id should be greater than zero."));
}
try
{
var itemToDelete = (from i in Values
where i.Id == id
select i).SingleOrDefault();
if (itemToDelete == null)
{
return await Task.FromResult<HttpResponseMessage>(Request.CreateResponse<string>(HttpStatusCode.NotFound,
string.Format("Unable to find a value for the Id {0}", id)));
}
Values.Remove(itemToDelete);
return await Task.FromResult<HttpResponseMessage>(Request.CreateResponse(HttpStatusCode.OK));
}
catch (Exception ex)
{
return Request.CreateResponse<string>(HttpStatusCode.InternalServerError, "Something went wrong."); // Default message if exception occured
}
}
And client Side:
private async static Task DeleteValue(int id)
{
var url = "http://localhost:13628/api/Values/" + id;
using (var client = new HttpClient())
{
var response = await client.DeleteAsync(url);
if (response.IsSuccessStatusCode)
{
await ReadValues();
}
else
{
var errorMessage = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(await response.Content.ReadAsStringAsync());
// Here Newtonsoft.Json Package is used to deserialize response content
Console.WriteLine(errorMessage);
Console.WriteLine(response.StatusCode);
}
}
}
Above code is working at my side.