ASP.NET Web API send JSON array - asp.net

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.

Related

Object is null after JsonConvert.DeserializeObject

I have looked at some forum posts and found no solution to my problem, so now I ask you for help. First i show you what the result of my HttpGet is and then i show you the not working deserialization.
Working example: I use the same code for an HttpGet to get a json result.
[HttpGet]
[Route("~/get_new_authtoken")]
public async Task<IActionResult> GetNewAuthTokenAsync()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://testApi/WebService/");
string APIConnection = _configuration.GetValue<string>("APIConnection");
HttpResponseMessage response = client.PostAsync("authtoken", new StringContent(string.Format(APIConnection))).Result;
if (response.IsSuccessStatusCode)
{
var token = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
return Ok(response.Content.ReadAsStringAsync().Result);
}
else
{
return BadRequest(response.Content.ReadAsStringAsync().Result);
}
}
catch (Exception ex)
{
SentrySdk.CaptureException(ex);
return Ok(ex.Message);
}
}
with following result when i call it via Postman
Not working deserialization: I store the token in a database and want to update it when it expires.
Object i want to desiralize in:
public class AuthToken
{
[JsonPropertyName("access_token")] public string AccessToken { get; set; }
[JsonPropertyName("refresh_token")] public string RefreshToken { get; set; }
[JsonPropertyName("token_type")] public string TokenType { get; set; }
[JsonPropertyName("expires_in")] public int ExpiresIn { get; set; }
}
when i add the following code to the httpget above to test the deserializationthe object Authtoken is always null.
AuthToken newAccessToken = new AuthToken();
newAccessToken = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
Like this->
if (response.IsSuccessStatusCode)
{
//To test
AuthToken newAccessToken = new AuthToken();
newAccessToken = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
//To test
var token = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
return Ok(response.Content.ReadAsStringAsync().Result);
}
else
{
return BadRequest(response.Content.ReadAsStringAsync().Result);
}
Updated the testint to following code:
AuthToken newAccessToken = new AuthToken();
var responseString = await response.Content.ReadAsStringAsync();
newAccessToken = JsonConvert.DeserializeObject<AuthToken>(responseString);
result of the responseString:
JsonPropertyNameAttribute is from System.Text.Json while JsonConvert.DeserializeObject is part of Newtonsoft.Json either switch to former completely by using System.Text.Json.JsonSerializer.Deserialize:
AuthToken newAccessToken = JsonSerializer.Deserialize<AuthToken>(...);
// or just use ReadFromJsonAsync instead of ReadAsStringAsync
Or use attributes for latter:
public class AuthToken
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
// ...
}

Call a rest web api in asp.net and receive error

Hi I want to call a rest Web Api and I use asp.net MVC+Web Api.
I write a get Token Method like below :
public TokenViewModel GetToken()
{
//string Result = string.Empty;
TokenViewModel token = null;
string baseAddress = "http://$$$$$$$$$$/api/security/login";
using (HttpClient client = new HttpClient())
{
try
{
var url = new Uri(baseAddress);
MultipartFormDataContent form = new MultipartFormDataContent();
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("UserName", "###");
parameters.Add("Password", "$$$");
HttpContent DictionaryItems = new FormUrlEncodedContent(parameters);
form.Add(DictionaryItems, "model");
var response = client.PostAsync(url.ToString(), form, System.Threading.CancellationToken.None);
if (response.Result.StatusCode == System.Net.HttpStatusCode.OK)
{
//Get body
var bodyRes = response.Result.Content.ReadAsStringAsync().Result;
token = JsonConvert.DeserializeObject<TokenViewModel>(bodyRes);
//Get Header
// var headers = response.Result.Headers.GetValues("appToken");
}
else
{
var a = response.Result.Content.ReadAsStringAsync().Result;
}
}
catch (Exception ex)
{
}
return token;
}
}
And also webController:
namespace WebAPI.Controllers
{
public class WebApiController : ApiController
{
private readonly GetToken_BLL _tokenService;
public WebApiController(GetToken_BLL tokenService)
{
_tokenService = tokenService;
}
public object Verfiybll { get; private set; }
public class stcAPIMessage
{
public string Message { get; set; }
public HttpStatusCode StatusCode { get; set; }
}
[HttpPost]
[Route("api/Token")]
public IHttpActionResult Token()
{
stcAPIMessage message = new stcAPIMessage();
GetToken_BLL tokenbll = new GetToken_BLL();
var result = tokenbll.GetToken();
if (result == null)
{
message.Message = "error in recieveing token";
message.StatusCode = HttpStatusCode.BadRequest;
return Content(message.StatusCode, message.Message);
}
else if (string.IsNullOrEmpty(result.Token))
{
message.Message = "Error";
message.StatusCode = HttpStatusCode.BadRequest;
return Content(message.StatusCode, message.Message);
}
return Ok(result);
}
}
}
When I run the program it throw out error:
An error occurred when trying to create a controller of type 'Web ApiController'.
Make sure that the controller has a parameter less public constructor.
System. Invalid Operation Exception Type 'WebAPI.Controllers.
Web ApiController' does not have a default constructor
System.
The parameter less constructor error is common in ASP.NET web applications that use dependency injection.
I have noticed there is a constructor parameter being used:
GetToken_BLL _tokenService
Use a dependency injection resolver for the type GetToken_BLL so that the parameter _tokenService can be instantiated.

returning a particular view with json response with asp.net

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();
}
}
}

Error retrieving data from Api Controller

I'm working on an ASP.NET Core Api and Xamarin forms client using Visual Studio 2017.
I'm getting an error
System.Runtime.Serialization.SerializationException: Invalid JSON string
because response.Content is null, when retrieving data from API but when paste this Url in browser "https://localhost:44305/api/Agreement/GetAgreementText/1" it shows data in the browser. When I run using client it's not hit to api method debug point .
Here is my APi method
[HttpGet]
[Route("GetAgreementText/{id}")]
public DefaultApiResult GetAgreementText(long Id)
{
Company com = _companyRepository.Get(Id);
string st = com.AgreementText;
DefaultApiResult result = new DefaultApiResult
{
Data = st
};
return result;
}
Here is my client application Api invoking method
public string GetAgreementTextLoading(long idCompany)
{
string agreementText = "";
// var token = _tokenService.GetLastActivateToken().Hash;
var clientURL = "https://localhost:44305/";
var client = new RestClient(clientURL);
var request = new RestRequest("api/Agreement/GetAgreementText/{Id}", Method.GET);
request.AddUrlSegment("Id", idCompany.ToString());
IRestResponse response = client.Execute(request);
AppRestResponse apiResponse = SimpleJson.DeserializeObject<AppRestResponse>(response.Content);
var statusMessage = "";
if (apiResponse.Success)
{
statusMessage = "Success.";
if (!string.IsNullOrEmpty(response.Content))
{
agreementText = apiResponse.Data.ToString();
}
else
{
throw new Exception("Invalid response");
}
}
else
{
agreementText = "Error retrieving agreement text";
}
return agreementText;
}
public class AppRestResponse
{
public bool Success { get; set; }
public object Data { get; set; }
public IEnumerable<AppRestReponseError> ErrorMessages { get; set; }
}
public class DefaultApiResult
{
public bool Success
{
get
{
return ErrorMessages.Count == 0;
}
private set { }
}
public List<ErrorMessage> ErrorMessages { get; set; }
public object Data { get; set; }
public DefaultApiResult()
{
ErrorMessages = new List<ErrorMessage>();
}
public DefaultApiResult(string errorMessage)
:this()
{
ErrorMessages.Add(new ErrorMessage()
{
Message = errorMessage
});
}
public DefaultApiResult(string[] errorMessages)
:this()
{
foreach (var errorMessage in errorMessages)
{
ErrorMessages.Add(new ErrorMessage()
{
Message = errorMessage
});
}
}
}
I'm not sure about the SimpleJson and the rest client you are using .
However , assuming you're using the RestSharp , it seems that there's no need to use the SimpleJson to deserialize response here .
I just remove the following codes :
IRestResponse response = client.Execute(request);
AppRestResponse apiResponse = SimpleJson.DeserializeObject<AppRestResponse>(response.Content);
and add the following two lines:
IRestResponse<AppRestResponse> response = client.Execute<AppRestResponse>(request);
var apiResponse= response.Data;
It works as expected .

XML File Model Mapping asp.net MVC3 ( Dynamically Map an xml file to a model class asp.net mvc3 )

I am trying to implement a payment gateway(INTUIT payment gateway). I would like to serialize an xml to an model class and save into my database. I am using Desktop Model for intuit payment gateway, as the hosted model is a pain to get working with especially ssl certificates, so i dont want to try that.
I must mention i am able to get the response using the below mentioned code, where i am stuck at the moment is serialize the xml and save the response into the database. This xml is pulled from a folder in my xmlfiles folder located in my project.
For sample xml format, check out this one. https://ipp.developer.intuit.com/0085_QuickBooks_Windows_SDK/qbms/0060_Documentation/Sending_Requests
this is an xml file i am trying to post to url (https://merchantaccount.ptc.quickbooks.com/j/AppGateway)
<?xml version="1.0"?>
<?qbmsxml version="4.5"?>
<QBMSXML>
<SignonMsgsRq>
<SignonDesktopRq>
<ClientDateTime>2012-07-25T17:13:45</ClientDateTime>
<ApplicationLogin>abc.abc.us</ApplicationLogin>
<ConnectionTicket>TGT-1-g42FGaMfOTQ82GcWFBpsuQ</ConnectionTicket>
</SignonDesktopRq>
</SignonMsgsRq>
<QBMSXMLMsgsRq>
<CustomerCreditCardChargeRq>
<TransRequestID>4540453787200</TransRequestID>
<CreditCardNumber>4111111111111111</CreditCardNumber>
<ExpirationMonth>12</ExpirationMonth>
<ExpirationYear>2016</ExpirationYear>
<IsCardPresent>false</IsCardPresent>
<Amount>10.00</Amount>
</CustomerCreditCardChargeRq>
</QBMSXMLMsgsRq>
</QBMSXML>
The Controller i use to make a post to the url
public ActionResult Index()
{
WebRequest req = null;
WebResponse rsp = null;
string fileName = Server.MapPath("~/XMLData/XMLFile1.xml");
string uri = "https://merchantaccount.ptc.quickbooks.com/j/AppGateway";
req = WebRequest.Create(uri);
//req.Proxy = WebProxy.GetDefaultProxy(); // Enable if using proxy
req.Method = "POST"; // Post method
req.ContentType = "application/x-qbmsxml"; // content type
// Wrap the request stream with a text-based writer
StreamWriter writer = new StreamWriter(req.GetRequestStream());
// Write the XML text into the stream
writer.WriteLine(this.GetTextFromXMLFile(fileName));
writer.Close();
// Send the data to the webserver
rsp = req.GetResponse();
// var resp = (Object)rsp.GetResponseStream();
if (rsp != null)
{
StreamReader inStream = new StreamReader(rsp.GetResponseStream());
var data = inStream.ReadToEnd();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(data);
string path = Server.MapPath("~/XMLData/SampleXmlE2E.xml");
xmlDoc.Save(path);//regenerates the xml file in different system.
}
return View();
//XElement root = new XElement("root");
//root.Add(new XElement("element1"));
//root.Add(new XElement("element2"));
//root.Add(new XAttribute("attribute1", "a value"));
//return new XmlResult(root);
}
private string GetTextFromXMLFile(string file)
{
StreamReader reader = new StreamReader(file);
string ret = reader.ReadToEnd();
reader.Close();
return ret;
}
private string SendRequest(Uri UriObj, string data)
{
string _result;
var request = (HttpWebRequest)WebRequest.Create(UriObj);
request.Method = "POST";
request.ContentType = "text/xml";
var writer = new StreamWriter(request.GetRequestStream());
writer.Write(data);
writer.Close();
var response = (HttpWebResponse)request.GetResponse();
var streamResponse = response.GetResponseStream();
var streamRead = new StreamReader(streamResponse);
_result = streamRead.ReadToEnd().Trim();
streamRead.Close();
streamResponse.Close();
response.Close();
return _result;
}
Any help would be appreciated. Thanks
Varun,
[Edit -update]
Based on this XML:
<?qbmsxml version="4.5"?>
<QBMSXML>
<SignonMsgsRq>
<SignonDesktopRq>
<ClientDateTime>2012-07-25T17:13:45</ClientDateTime>
<ApplicationLogin>app.app.login.url</ApplicationLogin>
<ConnectionTicket>TGT-1-g42FGaMfOTQ82GcWFBpsuQ</ConnectionTicket>
</SignonDesktopRq>
</SignonMsgsRq>
<QBMSXMLMsgsRq>
<CustomerCreditCardChargeRq>
<TransRequestID>4540453787200</TransRequestID>
<CreditCardNumber>4111111111111111</CreditCardNumber>
<ExpirationMonth>12</ExpirationMonth>
<ExpirationYear>2016</ExpirationYear>
<IsCardPresent>false</IsCardPresent>
<Amount>10.00</Amount>
</CustomerCreditCardChargeRq>
</QBMSXMLMsgsRq>
</QBMSXML>
Here's the class structure that you'd need to deserialize into as per the example above:
[XmlRoot("QBMSXML")]
public class QbmsXml
{
[XmlElement("SignonMsgsRq")]
public SignonMsgsRq SignonMsgsRq { get; set; }
[XmlElement("QBMSXMLMsgsRq")]
public QbmsXmlMsgsRq QbmsXmlMsgsRq { get; set; }
}
public class SignonMsgsRq
{
[XmlElement("SignonDesktopRq")]
public SignonDesktopRq SignonDesktopRq { get; set; }
}
public class SignonDesktopRq
{
[XmlElement("ClientDateTime")]
public DateTime ClientDateTime { get; set; }
[XmlElement("ApplicationLogin")]
public string ApplicationLogin { get; set; }
[XmlElement("ConnectionTicket")]
public string ConnectionTicket { get; set; }
}
public class QbmsXmlMsgsRq
{
[XmlElement("CustomerCreditCardChargeRq")]
public CustomerCreditCardChargeRq CustomerCreditCardChargeRq { get; set; }
}
public class CustomerCreditCardChargeRq
{
[XmlElement("TransRequestID")]
public Int64 TransRequestID { get; set; }
[XmlElement("CreditCardNumber")]
public string CreditCardNumber { get; set; }
[XmlElement("ExpirationMonth")]
public int ExpirationMonth { get; set; }
[XmlElement("ExpirationYear")]
public int ExpirationYear { get; set; }
[XmlElement("IsCardPresent")]
public bool IsCardPresent { get; set; }
[XmlElement("Amount")]
public double Amount { get; set; }
}
Just use the xmlSerialiser along the lines of:
class Program
{
private static T DeSerialize<T>(string fromXmlFile) where T: class
{
if (!File.Exists(fromXmlFile))
{
return default(T);
}
T deserializedClass;
var serializer = new XmlSerializer(typeof(T));
// ToDo: add error catching etc
using (var reader = new StreamReader(fromXmlFile))
{
deserializedClass = (T)serializer.Deserialize(reader);
}
return deserializedClass;
}
static void Main(string[] args)
{
var yourXmlFilePath = #"d:\temp\xmltest.xml";
var deserializedClass = DeSerialize<QbmsXml>(yourXmlFilePath);
Console.WriteLine(deserializedClass
.QbmsXmlMsgsRq
.CustomerCreditCardChargeRq.Amount);
Console.Read();
}
}
hope this helps.

Resources