I have a method on web service and I need to receive parameters with [HttpPost].
I am new at this, and I really don't know how.
I need to receive the following:
**** long requestId, string text, byte[] audio, short languageId****
public void AddAnswer (long requestId, string text, byte[] audio, short languageId)
{
string userIdWhoAnswers = (User as TokenPrincipal).userId.ToString();
long userId = Convert.ToInt64(userIdWhoAnswers);
using (var context = new WordsEntities())
{
Answers answer = new Answers();
answer.requestId = requestId;
answer.userId = 10;
answer.text = text;
answer.audioExtension = audio;
DateTime datee = DateTime.Now;
answer.timePosted = datee;
answer.languageId = languageId;
context.Answers.Add(answer);
context.SaveChanges();
}
}
This is my method but with HttpGet, I need to convert it to HttpPost.
Can someone please help me?
Looking your code I think you are sending the information using the body and not the url (in fact you are trying to send a byte array that usually isn't compatible with the query string).
For this reason you have to use the FromBody attribute near to the parameter name
public void AddAnswer ([FromBody] long requestId, [FromBody] string text, [FromBody] byte[] audio, [FromBody] short languageId)
moreover I think that the byte[] doesn't work. Probably you have to work with multipart
you can refer to this question and specially this link
TLDR; FromBody accepts just one parameter; try passing a JSON string with all required inputs in a single parameter to your HttpPost.
Related
So I've been working on this API and I didn't have issues until now when I tried figuring out how to make a POST method that takes an image as a parameter. In theory, this is how it should work:
From a web page, you will upload an image and then using the route to the API, the image information will be sent to the database like this:
Now, I've been searching for an answer to this on different several pages but none of them actually helped. In fact, the only guides that I've found were about integrating that method into a Web Api (see https://www.c-sharpcorner.com/article/uploading-image-to-server-using-web-api-2-0/) but this doesn't really work for me as I can't inherit some of the methods in my solution. For example, using the link above, I had issues with HttpContext.Current, and I would guess that is because of the solution that I am currently using. However, that's another question to be asked.
So my methods look pretty much like this:
public class RecipeController : Controller
{
private readonly Func<SqlConnection> _connFactory;
public RecipeController(Func<SqlConnection> connFactory)
{
_connFactory = connFactory;
}
[Route("v1/recipe/{recipeBy}")]
[HttpGet()]
public List<Recipe> GetRecipes(string recipeBy)
{
using (var con = _connFactory())
{
con.Open();
return con.Query<Recipe>("SELECT * FROM dbo.Recipe WHERE RecipeBy = #recipeBy", new { recipeBy }).ToList();
}
}
....
I am using Dapper to pass the values to the database.
Therefore, my question is: How can I write a POST method that takes an uploaded image as a parameter and then passes it to the database? I do realize that this question is pretty vague, as I didn't even provide reproducible code. The thing is, until now I didn't even figure out a correct way to start working on, so I couldn't really provide any useful code that you can help me with. Any tips, hints, advice, tutorials... Anything is welcome!
You can accomplish this by using the Html5 FileReader class to read the image to a string on the client-side and then post this to the api end-point:
function UploadImage()
{
var file = input[0].files[0];
var reader = new FileReader();
reader.onloadend = function () {
var imageDataString = reader.result;
// post the fileString value to your api here
}
if (file) {
reader.readAsDataURL(file);
}
}
Then on your Controller you would convert the Base64String into a byte[] and store it in your db:
if (imageDataString != null && imageDataString != String.Empty)
{
string imageDataParsed = imageDataString.Substring(imageDataString.IndexOf(',') + 1);
byte[] imageBytes = Convert.FromBase64String(imageDataParsed);
}
'DinnorApp.DinnorAppWeb2.addUsuarioConImagenDesktopRequest' is a 'type', which is not valid in the given context
I have a problem with that kind of error, my code is here
public int addUsuario(string nombreCompleto, string usuario, string correo, string contraseña, string palabraClave, byte[] imagen)
{
users = new Usuario();
DinnorAppWeb2.Usuario usuario3 = new DinnorAppWeb2.Usuario();
soap = new DinnorAppWeb2.WebService1SoapClient();
usuario3 = soap.addUsuarioConImagenDesktop(DinnorAppWeb2.addUsuarioConImagenDesktopRequest(nombreCompleto, usuario, correo, contraseña, palabraClave, imagen));
users.nombreCompleto = usuario3.nombreCompleto;
users.usuario = usuario3.usuario;
if (users.nombreCompleto != null && users.usuario != null)
{
return 1;
}
return 0;
}
The code above, is in winform, that information i use webservice
On the references file is
// CODEGEN: Parameter 'imagen' requires additional schema information that cannot be captured using the parameter mode. The specific attribute is 'System.Xml.Serialization.XmlElementAttribute'.
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/addUsuarioConImagen", ReplyAction="*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
DinnorApp.DinnorAppWeb2.addUsuarioConImagenResponse addUsuarioConImagen(DinnorApp.DinnorAppWeb2.addUsuarioConImagenRequest request);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/addUsuarioConImagen", ReplyAction="*")]
System.Threading.Tasks.Task<DinnorApp.DinnorAppWeb2.addUsuarioConImagenResponse> addUsuarioConImagenAsync(DinnorApp.DinnorAppWeb2.addUsuarioConImagenRequest request);
The code above, is when i call a service reference(webservice)
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/addUsuario", ReplyAction="*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
int addUsuario(string nombreCompleto, string usuario, string correo, string contraseña, string palabraClave);
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/addUsuario", ReplyAction="*")]
System.Threading.Tasks.Task<int> addUsuarioAsync(string nombreCompleto, string usuario, string correo, string contraseña, string palabraClave);
The code above, i can invoke a method with parameter easily, but the error
i think the problem is the byte[] but i don't know why, because if i change byte[] to string or int or similar in parameter, that would be normal like rest.
The byte[] is for save or add image on mysql. So how can i solve it?
I hope someone can help.
Sorry for my english.
You would realize it that somewords is in spanish.
EDIT:
I solved it , this is the correct code:
DinnorAppWeb2.addUsuarioConImagenDesktopRequest add2 = new DinnorAppWeb2.addUsuarioConImagenDesktopRequest(nombreCompleto,usuario,correo,contraseña,palabraClave,imagen);
soap.addUsuarioConImagenDesktop(add2);
Question Background:
Update:
I'm still not sure how to go about extracting the relevant information from this response. I have tried setting my response type to JSON but still receive the response as shown below. I have taken into account what has been said in regards to using NameValueCollection but still cant see how this will help with such a large response. Ideally I'd like this mapped to an object structure of some kind, it dosen't necessarily have to be JSON.
Question:
I'm currently using the PayPal Api 'ExpressCheckout' method to allow users to pay for items on my test site. A HTTP response from the API provides a large response containing key information I need to extract - such as the buyers address, if the payment was succesful etc.
The Issue:
Currently I'm stuck on how to work with the response. Ideally I'd convert the data to a JSON string then use Newtonsoft to map the data to C# classes thus allowing easy access to the data. Here is an example of the Httpresponse:
TOKEN=EC%2XXXXXXXXXXXXXXXXXR&BILLINGAGREEMENTACCEPTEDSTATUS=0&CHECKOUTSTATUS=PaymentActionNotInitiated&TIMESTAMP=2015%2d01%2d02T21%3a11%3a30Z&CORRELATIONID=ab184fdba7a30&ACK=Success&VERSION=88%2e0&BUILD=14443165&EMAIL=test%40aol%2ecom&PAYERID=3XXXXXXXXXX4N&PAYERSTATUS=verified&BUSINESS=Test%20Biz%27s%20Test%20Store&FIRSTNAME=Joe&LASTNAME=King&COUNTRYCODE=GB&SHIPTONAME=Joe%20King%27s%20Test%20Store&SHIPTOSTREET=1%20Main%20Terrace&SHIPTOCITY=Wolverhampton&SHIPTOSTATE=West%20Midlands&SHIPTOZIP=W12%204LQ&SHIPTOCOUNTRYCODE=GB&SHIPTOCOUNTRYNAME=United%20Kingdom&ADDRESSSTATUS=Confirmed&CURRENCYCODE=GBP&AMT=15%2e56&ITEMAMT=15%2e56&SHIPPINGAMT=0%2e00&HANDLINGAMT=0%2e00&TAXAMT=0%2e00&INSURANCEAMT=0%2e00&SHIPDISCAMT=0%2e00&L_NAME0=ItemOne&L_QTY0=4&L_TAXAMT0=0%2e00&L_AMT0=3%2e89&L_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_ITEMHEIGHTVALUE0=%20%20%200%2e00000&PAYMENTREQUEST_0_CURRENCYCODE=GBP&PAYMENTREQUEST_0_AMT=15%2e56&PAYMENTREQUEST_0_ITEMAMT=15%2e56&PAYMENTREQUEST_0_SHIPPINGAMT=0%2e00&PAYMENTREQUEST_0_HANDLINGAMT=0%2e00&PAYMENTREQUEST_0_TAXAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEAMT=0%2e00&PAYMENTREQUEST_0_SHIPDISCAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false&PAYMENTREQUEST_0_SHIPTONAME=Joe%20King%27s%20Test%20Store&PAYMENTREQUEST_0_SHIPTOSTREET=1%20Main%20Terrace&PAYMENTREQUEST_0_SHIPTOCITY=Wolverhampton&PAYMENTREQUEST_0_SHIPTOSTATE=West%20Midlands&PAYMENTREQUEST_0_SHIPTOZIP=W12%204LQ&PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE=GB&PAYMENTREQUEST_0_SHIPTOCOUNTRYNAME=United%20Kingdom&PAYMENTREQUEST_0_ADDRESSSTATUS=Confirmed&L_PAYMENTREQUEST_0_NAME0=ItemOne&L_PAYMENTREQUEST_0_QTY0=4&L_PAYMENTREQUEST_0_TAXAMT0=0%2e00&L_PAYMENTREQUEST_0_AMT0=3%2e89&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE0=%20%20%200%2e00000&PAYMENTREQUESTINFO_0_ERRORCODE=0
If anyone could give me an easy way to map this data to a C# object that would be great.
Is there any specific reason why you want it in JSON format? If its not requirement and if you can live with key value pair then here is one way you can process response as key value pair.
public partial class Form1 : Form
{
Dictionary<string, string> processedResponse = null;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string rawResponse = "TOKEN=EC%2XXXXXXXXXXXXXXXXXR&BILLINGAGREEMENTACCEPTEDSTATUS=0&CHECKOUTSTATUS=PaymentActionNotInitiated&TIMESTAMP=2015%2d01%2d02T21%3a11%3a30Z&CORRELATIONID=ab184fdba7a30&ACK=Success&VERSION=88%2e0&BUILD=14443165&EMAIL=test%40aol%2ecom&PAYERID=3XXXXXXXXXX4N&PAYERSTATUS=verified&BUSINESS=Test%20Biz%27s%20Test%20Store&FIRSTNAME=Joe&LASTNAME=King&COUNTRYCODE=GB&SHIPTONAME=Joe%20King%27s%20Test%20Store&SHIPTOSTREET=1%20Main%20Terrace&SHIPTOCITY=Wolverhampton&SHIPTOSTATE=West%20Midlands&SHIPTOZIP=W12%204LQ&SHIPTOCOUNTRYCODE=GB&SHIPTOCOUNTRYNAME=United%20Kingdom&ADDRESSSTATUS=Confirmed&CURRENCYCODE=GBP&AMT=15%2e56&ITEMAMT=15%2e56&SHIPPINGAMT=0%2e00&HANDLINGAMT=0%2e00&TAXAMT=0%2e00&INSURANCEAMT=0%2e00&SHIPDISCAMT=0%2e00&L_NAME0=ItemOne&L_QTY0=4&L_TAXAMT0=0%2e00&L_AMT0=3%2e89&L_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_ITEMHEIGHTVALUE0=%20%20%200%2e00000&PAYMENTREQUEST_0_CURRENCYCODE=GBP&PAYMENTREQUEST_0_AMT=15%2e56&PAYMENTREQUEST_0_ITEMAMT=15%2e56&PAYMENTREQUEST_0_SHIPPINGAMT=0%2e00&PAYMENTREQUEST_0_HANDLINGAMT=0%2e00&PAYMENTREQUEST_0_TAXAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEAMT=0%2e00&PAYMENTREQUEST_0_SHIPDISCAMT=0%2e00&PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false&PAYMENTREQUEST_0_SHIPTONAME=Joe%20King%27s%20Test%20Store&PAYMENTREQUEST_0_SHIPTOSTREET=1%20Main%20Terrace&PAYMENTREQUEST_0_SHIPTOCITY=Wolverhampton&PAYMENTREQUEST_0_SHIPTOSTATE=West%20Midlands&PAYMENTREQUEST_0_SHIPTOZIP=W12%204LQ&PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE=GB&PAYMENTREQUEST_0_SHIPTOCOUNTRYNAME=United%20Kingdom&PAYMENTREQUEST_0_ADDRESSSTATUS=Confirmed&L_PAYMENTREQUEST_0_NAME0=ItemOne&L_PAYMENTREQUEST_0_QTY0=4&L_PAYMENTREQUEST_0_TAXAMT0=0%2e00&L_PAYMENTREQUEST_0_AMT0=3%2e89&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE0=%20%20%200%2e00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE0=%20%20%200%2e00000&PAYMENTREQUESTINFO_0_ERRORCODE=0";
//Process response
processedResponse = ProcessResponse(rawResponse);
//Use received data e.g.
//Get First name
string fName = GetRecordValue("FIRSTNAME");
//Get Last name
string lName = GetRecordValue("LASTNAME");
}
private Dictionary<string,string> ProcessResponse(string response)
{
Dictionary<string, string> responseData = new Dictionary<string, string>();
if(!string.IsNullOrWhiteSpace(response))
{
string[] firstPass = response.Split(new char[] { '&' });
foreach(string pair in firstPass)
{
string[] secondPass = pair.Split(new char[] { '=' });
if(secondPass!=null && secondPass.Length>0)
{
responseData.Add(secondPass[0].Trim(), secondPass[1].Trim());
}
}
}
return responseData;
}
private string GetRecordValue(string record)
{
string recordValue = null;
if(processedResponse!=null)
{
if(!string.IsNullOrWhiteSpace(record) && processedResponse.ContainsKey(record))
{
recordValue= processedResponse[record];
}
}
return recordValue;
}
}
Still unsure what's the problem with dealing with it as a NameValueCollection.
E.g.
//NameValueCollection
//or use HttpUtility.ParseQueryString(some_string_of_names_values)
var foo = Request.QueryString;
var bar = foo["FIRSTNAME"]; //based on above this is "Joe"
Update:
It is response string which is being processed here and not request hence you wont be able to retrieve details using Request.QueryString
As stated in comments:
string rawResponse = "TOKEN=EC%2XXXXXXXXXXXXXXXXXR&BILLINGAGREEMENTACCEPTEDSTATUS=0&CHECKOUTSTATUS=PaymentActionNotInitiated&TIMESTAMP=2015%2d01%2d02T21%3a11%3a30Z&CORRELATIONID=ab184fdba7a30&ACK=Success&VERSION=88...."
var foo = HttpUtility.ParseQueryString(rawResponse); //NameValueCollection
var bar = foo["FIRSTNAME"]; //Joe
Please take a look at the following code. It's in handler.asxh.
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/json";
new RequestManagementFacade().PinRequest(Int32.Parse(context.Request.QueryString["requestId"]), (Boolean.Parse(context.Request.QueryString["isPinned"])));
}
This is showing the following error:
Value cannot be null. Parameter name: String
There is value being passed as I have checked the context request query string, however, the code breaks at this stage.
This handler will connect to the business logic layer.
There is value being passed as i have checke dthe context request query string
I strongly suspect your diagnostics are incorrect then. Values don't magically go missing - you need to question your assumptions. This is easy to debug through though. I would suggest changing your code to:
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/json";
string requestId = context.Request.QueryString["requestId"];
string isPinned = context.Request.QueryString["isPinned"];
var facade = new RequestManagementFacade();
facade.PinRequest(Int32.Parse(requestId), Boolean.Parse(isPinned));
}
It's then really simple to step through and find out what's going on.
It is likely that either context.Request.QueryString["requestId"] or context.Request.QueryString["isPinned"] is not returning a valid string value. Check that both values are passed in the query string with the proper IDs, those being of course requestId and isPinned.
Okay solved when passing the values to the handler i inserted it as
"PinRequest.ashx?="+requestId+isPinned"
Which gave me the result 2True
So i realised the hiccup was with not including the string names
"PinRequest.ashx?requestId=" + this._requestId + "&isPinned=" + this._isPinned
Thanks for you help guys
LeviBotelho Thank you made me check something i was missing out when checking as its javascript
experienced the error while using Int32.Parse(myString) to convert string to int and afterwards assign the value to an object's attribute. Using another method for converting(Convert.ToInt32(myString)) string to int worked for me.
I had a webmethod working which returned a byte array to the caller:
public byte[] DownloadPDF(string URI)
I had to change this to return another output (a string). So, I decided to change the method completely by now returning void and having 3 parameters like this:
public void DownloadFile(string URI, out byte[] docContents, out string returnFiletype)
My web service compiles correctly but I suspect something is wrong with the 2nd parameter (i.e. the byte array) because when I "Add Web Reference" and build my proxy class, the method has only 2 parameters, not 3):
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/DownloadFile", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlElementAttribute("docContents", DataType="base64Binary")]
public byte[] DownloadFile(string URI, out string returnFiletype) {
object[] results = this.Invoke("DownloadFile", new object[] {
URI});
returnFiletype = ((string)(results[1]));
return ((byte[])(results[0]));
}
I don't see why my 2nd parameter, the byte array, is being ignored, but it appears to be the source of the problem.
This of course messes me up in the web client app where I get an error message at compile time:
No overload for method 'DownloadFile' takes '3' arguments
Here is the code in the web client where I need to pass 3 arguments:
myBrokerASMXProxy.ASMXProxy.FileService client = new myASMXProxy.ASMXProxy.FileService();
byte[] fileDataBytes;
string fileType;
client.DownloadFile(URI, fileDataBytes, fileType);
I am thinking of changing it back to return a byte array and add just a single "out" parameter but I thought I should ask you experts about this and in general, what is the best practice for handling multiple output requirements.
Why don't your try putting this signature:
public bool DownloadFile(string URI, out byte[] docContents, out string returnFiletype)
To see what happens? I agree with Jon Skeet, but you can still can return a bool with the result of the operation
The byte array isn't being ignored - it's being put as the return type instead. I don't know why it's doing that, but it makes more sense in my view. I wouldn't use out parameters in a void method. I suspect the proxy generator just takes any method with out parameters and turns the first one into a return type.