I'm writing my first custom Activity for a UiPath RPA workflow in which I need to async send a filestream to the backend. This is what I've come up with but I just have this feeling that this doensn't quite work:
class SendFiles : AsyncCodeActivity<string>
{
private readonly HttpClient client = new HttpClient();
private readonly string url = "";
[Category("Input")]
[RequiredArgument]
public InArgument<List<string>> Files { get; set; }
[Category("Input")]
[RequiredArgument]
public string BearerToken { get; set; }
[Category("Output")]
public OutArgument JsonResult { get; set; }
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
foreach (var filePath in Files.Get(context))
{
try
{
using (FileStream fs = File.Open(filePath, FileMode.Open, FileAccess.Read))
{
HttpContent content = new StreamContent(fs);
client.PostAsync(url, content);
}
}
catch (IOException e)
{
Console.WriteLine(e.Message);
throw;
}
}
return null;
}
protected override string EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
{
throw new NotImplementedException();
}
}
After sending the whole batch, I want to wait for the result of te backend processing all these files. how can I accomplish this?
// make outer content
MultipartFormDataContent formdata = new MultipartFormDataContent();
...
// in foreach add every filestream to outer content
FileStream fs = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
HttpContent content = new StreamContent(fs);
string name = GetFileName(filePath);
content.Headers.Add("Content-Type", GetFileType(name));
formdata.Add(content, "files", name);
...
// after foreach, send whole outer content in one go
var resultPost = client.PostAsync(url, formdata).Result;
response = resultPost.Content.ReadAsStringAsync().Result;
succesfullRequest = resultPost.IsSuccessStatusCode;
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();
}
}
}
I’m sending from an asp.net page Json data from javascript, the JS data/object was previously serialized and the sent to my asp.net genericHandler.ashx page.
On server side I’m using Json.net, this is my code in the generic handler:
public void ProcessRequest(HttpContext context)
{
int numberOfFiles = 0;
MyGlobalSettings myGlobalSett = new MyGlobalSettings();
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
string jsonString = string.Empty;
context.Request.InputStream.Position = 0;
using (StreamReader inputStream = new System.IO.StreamReader(context.Request.InputStream))
{
jsonString = inputStream.ReadToEnd();
}
MyData contentType = new MyData();
contentType = jsonSerializer.Deserialize<MyData>(jsonString);
Debug.WriteLine("Context 1:" + contentType.name);
context.Request.InputStream.Position = 0;
string json;
using (var reader = new StreamReader(context.Request.InputStream))
{
json = reader.ReadToEnd();
}
MyData contentType2 = new MyData();
contentType2=JsonConvert.DeserializeObject<MyData>(json);
Debug.WriteLine("Context 2:" + contentType2.name);
My deserialized object class
public class MyData
{
public string name { get; set; }
public string lastName { get; set; }
public string age { get; set; }
}
This is the error I get.
An exception of type 'System.NullReferenceException' occurred in Demo_xss_prevention_04.dll but was not handled in user code
Additional information: Object reference not set to an instance of an object.
I've tried the built in .net Json serializer (JavaScriptSerializer), and it works, but with Json.net I get this error. How can I fix it?
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 was wondering if it is possible to use an httphandler to download an image, serve that image to the browser and then do it again.
I currently have access to a url that produces a snapshot image from an ip camera that I would like to continue to pull from. Essentially making a slide show of the snapshots indefinitely.
I have already figured out how to download the image and display it. The next step would to, for a lack of better terms, recursively repeat the process.
I certainly can do this with Ajax calls from the client but would much rather remove handle it at the server.
Thanks,
Chad
using Newtonsoft.Json.Linq;
using System;
using System.Net;
using System.Web;
using System.Threading;
namespace Something.App_Code
{
class CameraSnapshotHandler : IHttpAsyncHandler
{
public bool IsReusable { get { return false; } }
public CameraSnapshotHandler() { }
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
{
SnapshotAsynchOperation asynch = new SnapshotAsynchOperation(cb, context, extraData);
asynch.StartAsyncWork();
return asynch;
}
public void EndProcessRequest(IAsyncResult result) { }
public void ProcessRequest(HttpContext context)
{
throw new InvalidOperationException();
}
}
class SnapshotAsynchOperation : IAsyncResult
{
private bool _completed;
private Object _state;
private AsyncCallback _callback;
private HttpContext _context;
bool IAsyncResult.IsCompleted { get { return _completed; } }
WaitHandle IAsyncResult.AsyncWaitHandle { get { return null; } }
Object IAsyncResult.AsyncState { get { return _state; } }
bool IAsyncResult.CompletedSynchronously { get { return false; } }
public SnapshotAsynchOperation(AsyncCallback callback, HttpContext context, Object state)
{
_callback = callback;
_context = context;
_state = state;
_completed = false;
}
public void StartAsyncWork()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(StartAsyncTask), null);
}
private void StartAsyncTask(Object workItemState)
{
using (var client = new WebClient())
{
// Get Json data
string username;
string password;
using (var credClient = new WebClient())
{
dynamic stuff = JObject.Parse(credClient.DownloadString(new Uri("http://www.some-url.com/servicestack/equipment-credentials.json?equipmentId=" + _context.Request.QueryString["id"])));
username = stuff.Username;
password = stuff.Password;
}
// Wait until we have full buffer before displaying
_context.Response.BufferOutput = true;
// Set content type to match
_context.Response.ContentType = "image/png";
// Digest Authenticate
client.Credentials = new NetworkCredential(username, password);
// Download into bit array
byte[] content = client.DownloadData("http://some-url/cgi/image.php?type=snapshot");
// Output stream to client
_context.Response.OutputStream.Write(content, 0, content.Length);
}
_completed = true;
_callback(this);
}
}
}
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.