The remote server returned an error: (400) Bad Request. - request

I am trying to post a message on a Facebook user's profile using Facebook API. It happens sometimes after authentication to send a message but the second time it always returns this error (just to mention that I use this for asp.net webapplication):
An error occurred:The remote server returned an error: (400) Bad Request.
System.Net.WebException: The remote server returned an error: (400) Bad Request. at System.Net.HttpWebRequest.GetResponse() at Facebook.FacebookAPI.MakeRequest(Uri url, HttpVerb httpVerb, Dictionary`2 args) in \wwwroot\App_Code\FacebookAPI.cs:line 185 at Facebook.FacebookAPI.Call(String relativePath, HttpVerb httpVerb, Dictionary`2 args) in \wwwroot\App_Code\FacebookAPI.cs:line 134 at Facebook.FacebookAPI.Post(String relativePath, Dictionary`2 args) in \wwwroot\App_Code\FacebookAPI.cs:line 107 at Views_Publish_to_facebook.btnSend_Click(Object sender, EventArgs e) in \wwwroot\Views\MarketingTool\Publish_to_facebook.aspx.cs:line 90
What could I do?
this is the login button
<fb:login-button autologoutlink='true' perms='read_stream,publish_stream,offline_access' onlogin='window.location.reload()'>
</fb:login-button>
Facebook C# SDK
This is my Facebook API code.
/*
* Copyright 2010 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Web;
using System.Web.Script.Serialization;
namespace Facebook
{
enum HttpVerb
{
GET,
POST,
DELETE
}
/// <summary>
/// Wrapper around the Facebook Graph API.
/// </summary>
public class FacebookAPI
{
/// <summary>
/// The access token used to authenticate API calls.
/// </summary>
public string AccessToken { get; set; }
/// <summary>
/// Create a new instance of the API, with public access only.
/// </summary>
public FacebookAPI()
: this(null) { }
/// <summary>
/// Create a new instance of the API, using the given token to
/// authenticate.
/// </summary>
/// <param name="token">The access token used for
/// authentication</param>
public FacebookAPI(string token)
{
AccessToken = token;
}
/// <summary>
/// Makes a Facebook Graph API GET request.
/// </summary>
/// <param name="relativePath">The path for the call,
/// e.g. /username</param>
public JSONObject Get(string relativePath)
{
return Call(relativePath, HttpVerb.GET, null);
}
/// <summary>
/// Makes a Facebook Graph API GET request.
/// </summary>
/// <param name="relativePath">The path for the call,
/// e.g. /username</param>
/// <param name="args">A dictionary of key/value pairs that
/// will get passed as query arguments.</param>
//public JSONObject Get(string relativePath,
// Dictionary<string, string> args)
public JSONObject Get(string relativePath,
Dictionary<string, string> args)
{
return Call(relativePath, HttpVerb.GET, args);
}
/// <summary>
/// Makes a Facebook Graph API DELETE request.
/// </summary>
/// <param name="relativePath">The path for the call,
/// e.g. /username</param>
public JSONObject Delete(string relativePath)
{
return Call(relativePath, HttpVerb.DELETE, null);
}
/// <summary>
/// Makes a Facebook Graph API POST request.
/// </summary>
/// <param name="relativePath">The path for the call,
/// e.g. /username</param>
/// <param name="args">A dictionary of key/value pairs that
/// will get passed as query arguments. These determine
/// what will get set in the graph API.</param>
public JSONObject Post(string relativePath,
Dictionary<string, string> args)
{
return Call(relativePath, HttpVerb.POST, args);
}
/// <summary>
/// Makes a Facebook Graph API Call.
/// </summary>
/// <param name="relativePath">The path for the call,
/// e.g. /username</param>
/// <param name="httpVerb">The HTTP verb to use, e.g.
/// GET, POST, DELETE</param>
/// <param name="args">A dictionary of key/value pairs that
/// will get passed as query arguments.</param>
private JSONObject Call(string relativePath,
HttpVerb httpVerb,
Dictionary<string, string> args)
{
Uri baseURL = new Uri("https://graph.facebook.com");
//relativePath = "/me";
Uri url = new Uri(baseURL, relativePath);
if (args == null)
{
args = new Dictionary<string, string>();
}
if (!string.IsNullOrEmpty(AccessToken))
{
args["access_token"] = AccessToken;
}
JSONObject obj = JSONObject.CreateFromString(MakeRequest(url,
httpVerb,
args));
if (obj.IsDictionary && obj.Dictionary.ContainsKey("error"))
{
throw new FacebookAPIException(obj.Dictionary["error"]
.Dictionary["type"]
.String,
obj.Dictionary["error"]
.Dictionary["message"]
.String + " -> " + url + " " + httpVerb + " " + args);
}
return obj;
}
/// <summary>
/// Make an HTTP request, with the given query args
/// </summary>
/// <param name="url">The URL of the request</param>
/// <param name="verb">The HTTP verb to use</param>
/// <param name="args">Dictionary of key/value pairs that represents
/// the key/value pairs for the request</param>
private string MakeRequest(Uri url, HttpVerb httpVerb,
Dictionary<string, string> args)
{
if (args != null && args.Keys.Count > 0 && httpVerb == HttpVerb.GET)
{
url = new Uri(url.ToString() + EncodeDictionary(args, true));
}
//throw new Exception(url.AbsoluteUri + " ---- " + url.AbsolutePath);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = httpVerb.ToString();
if (httpVerb == HttpVerb.POST)
{
string postData = EncodeDictionary(args, false);
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] postDataBytes = encoding.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postDataBytes.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(postDataBytes, 0, postDataBytes.Length);
requestStream.Close();
}
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
try
{
//using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
//throw new Exception(response.ResponseUri + " tra " + response.Server);
{
StreamReader reader
= new StreamReader(response.GetResponseStream());
return reader.ReadToEnd();
}
}
catch (WebException e)
{
throw new FacebookAPIException("Server Error", e.Message + " resp: " + request.GetResponse() + " " + response.ResponseUri + " tra " + response.Server);
}
}
/// <summary>
/// Encode a dictionary of key/value pairs as an HTTP query string.
/// </summary>
/// <param name="dict">The dictionary to encode</param>
/// <param name="questionMark">Whether or not to start it
/// with a question mark (for GET requests)</param>
private string EncodeDictionary(Dictionary<string, string> dict,
bool questionMark)
{
StringBuilder sb = new StringBuilder();
if (questionMark)
{
sb.Append("?");
}
foreach (KeyValuePair<string, string> kvp in dict)
{
sb.Append(HttpUtility.UrlEncode(kvp.Key));
sb.Append("=");
//NOTE: This line causes problems with access_token. The url encoding messes up the access_token, so for now I'm just adding it directly
//if the key == "access_token"
//sb.Append(HttpUtility.UrlEncode(kvp.Value));
if (kvp.Key.ToLower() == "access_token")
{
sb.Append(kvp.Value);
//sb.Append(HttpUtility.UrlEncode(HttpUtility.UrlDecode(kvp.Value)));
}
else
{
sb.Append(HttpUtility.UrlEncode(kvp.Value));
}
sb.Append("&");
}
sb.Remove(sb.Length - 1, 1); // Remove trailing &
return sb.ToString();
}
}
}

Related

WPF ListView with large collection hangs GUI

++++++ Link to example project ++++++
I have a file that can contain thousands of lines of logged messages. I am parsing this file and adding each line (as a log event) to a collection. This collection should then be shown in a ListView.
As below:
<ListView
Grid.Row="0"
Margin="5"
ItemsSource="{Binding SelectedSerilogFileLog.LogEvents}"
ScrollViewer.CanContentScroll="False"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectedItem="{Binding SelectedLogEvent}"
SelectionMode="Single">
The parsing of the file (this one contains 2500+ log events) and adding to the collection takes around 100ms. Then when the bound collection is updated with the ReplaceContent method (this suppresses the collectionchanged event firing on every item added) the GUI hangs, but I cannot see why or what can be causing this.
MainWindow.cs
...
/// <summary>
///
/// </summary>
public SerilogFileLog SelectedSerilogFileLog
{
get => selectedSerilogFileLog; set
{
if (selectedSerilogFileLog != null)
{
SelectedSerilogFileLog.OnSerilogParserFinished -= OnSerilogParserFinished;
SelectedSerilogFileLog.OnSerilogParserProgressChanged -= OnSerilogParserProgressChanged;
}
selectedSerilogFileLog = value;
if (selectedSerilogFileLog != null)
{
ParserProgress = 0;
SelectedSerilogFileLog.OnSerilogParserFinished += OnSerilogParserFinished;
SelectedSerilogFileLog.OnSerilogParserProgressChanged += OnSerilogParserProgressChanged;
sw.Start();
SelectedSerilogFileLog.Parse();
}
NotifyPropertyChanged(nameof(SelectedSerilogFileLog));
}
}
...
private void Button_Click(object sender, RoutedEventArgs e)
{
SelectedSerilogFileLog = null;
SelectedSerilogFileLog = new SerilogFileLog() { FilePath = "Application20210216.log" };
}
The parsing and loading of the items occurs in a separate Task.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace LargeListViewTest.Classes
{
public class SerilogFileLog : INotifyPropertyChanged
{
private LogEvent lastLogEvent;
private ObservableCollectionEx<LogEvent> logEvents;
private string name;
private string description;
private string filePath;
private Regex patternMatching;
private string matchExpression = #"^(?<DateTime>[^|]+)\| (?<Level>[^|]+) \| (?<MachineName>[^|]+) \| (?<Source>[^|]+) \| (?<Message>[^$]*)$";
public delegate void SerilogParserProgressHandler(int Percentage);
public delegate void SerilogParserFinishedHandler();
/// <summary>
///
/// </summary>
public event SerilogParserProgressHandler OnSerilogParserProgressChanged;
/// <summary>
///
/// </summary>
public event SerilogParserFinishedHandler OnSerilogParserFinished;
/// <summary>
/// Gets or sets the LogEvents.
/// </summary>
public ObservableCollectionEx<LogEvent> LogEvents { get => logEvents; private set { logEvents = value; NotifyPropertyChanged(nameof(LogEvents)); } }
/// <summary>
/// Gets or sets the Name.
/// </summary>
public string Name { get => name; private set { name = value; NotifyPropertyChanged(nameof(Name)); } }
/// <summary>
/// Gets or sets the Description.
/// </summary>
public string Description { get => description; private set { description = value; NotifyPropertyChanged(nameof(Description)); } }
/// <summary>
/// Gets or sets the FilePath.
/// </summary>
public string FilePath
{
get => filePath;
set
{
filePath = value;
Name = Path.GetFileNameWithoutExtension(value);
Description = FilePath;
}
}
/// <summary>
///
/// </summary>
public SerilogFileLog()
{
LogEvents = new ObservableCollectionEx<LogEvent>();
patternMatching = new Regex(matchExpression, RegexOptions.Singleline | RegexOptions.Compiled);
}
/// <summary>
///
/// </summary>
public void Parse()
{
Task task = Task.Factory.StartNew(() => { InternalParse(); });
}
/// <summary>
///
/// </summary>
private void InternalParse()
{
OnSerilogParserProgressChanged?.Invoke(0);
try
{
if (!string.IsNullOrWhiteSpace(FilePath))
{
Console.WriteLine("Starting parse for {0}", FilePath);
long currentLength = 0;
FileInfo fi = new FileInfo(FilePath);
if (fi.Exists)
{
Console.WriteLine("Parsing Serilog file: {0}.", FilePath);
fi.Refresh();
List<LogEvent> parsedLogEvents = new List<LogEvent>();
StringBuilder sb = new StringBuilder();
using (FileStream fileStream = fi.Open(FileMode.Open, FileAccess.Read, FileShare.Write))
using (var streamReader = new StreamReader(fileStream))
{
while (streamReader.Peek() != -1)
{
sb.Append(streamReader.ReadLine());
LogEvent newLogEvent = ParseLogEvent(sb.ToString());
if (newLogEvent != null)
{
parsedLogEvents.Add(newLogEvent);
lastLogEvent = newLogEvent;
}
OnSerilogParserProgressChanged?.Invoke((int)(currentLength * 100 / fi.Length));
currentLength = currentLength + sb.ToString().Length;
sb.Clear();
}
}
LogEvents.ReplaceContent(parsedLogEvents);
}
Console.WriteLine("Finished parsing Serilog {0}.", FilePath);
}
}
catch (Exception ex)
{
Console.WriteLine("Error parsing Serilog." + ex.Message);
}
OnSerilogParserProgressChanged?.Invoke(100);
SerilogParserFinishedHandler onSerilogParserFinished = OnSerilogParserFinished;
if (onSerilogParserFinished == null)
return;
OnSerilogParserFinished();
}
/// <summary>
///
/// </summary>
/// <param name="mes"></param>
/// <returns></returns>
private LogEvent ParseLogEvent(string mes)
{
LogEvent logEvent = new LogEvent();
Match matcher = patternMatching.Match(mes);
try
{
if (matcher.Success)
{
logEvent.Message = matcher.Groups["Message"].Value;
DateTime dt;
if (!DateTime.TryParse(matcher.Groups["DateTime"].Value, out dt))
{
Console.WriteLine("Failed to parse date {Value}", matcher.Groups["DateTime"].Value);
}
logEvent.DateTime = dt;
logEvent.Level = matcher.Groups["Level"].Value;
logEvent.MachineName = matcher.Groups["MachineName"].Value;
logEvent.Source = matcher.Groups["Source"].Value;
}
else
{
if ((string.IsNullOrEmpty(mes) || (!Char.IsDigit(mes[0])) || !Char.IsDigit(mes[1])) && lastLogEvent != null)
{
// seems to be a continuation of the previous line, add it to the last event.
lastLogEvent.Message += Environment.NewLine;
lastLogEvent.Message += mes;
logEvent = null;
}
else
{
Console.WriteLine("Message parsing failed.");
}
if (logEvent != null)
logEvent.Message = mes;
}
}
catch (Exception ex)
{
Console.WriteLine("ParseLogEvent exception." + ex.Message);
}
return logEvent;
}
#region INotify
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string p) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p));
#endregion
}
}
I have an ObservableCollectionEx class that extends the default ObservableCollection, this class suppresses the collection changed event until all the items have been added/replaced.
/// <summary>
/// Adds the supplied items to the collection and raises a single <see cref="CollectionChanged"/> event
/// when the operation is complete.
/// </summary>
/// <param name="items">The items to add.</param>
public void AddRange(IEnumerable<T> items, bool notifyAfter = true)
{
if (null == items)
{
throw new ArgumentNullException("items");
}
if (items.Any())
{
try
{
SuppressChangeNotification();
CheckReentrancy();
foreach (var item in items)
{
Add(item);
}
}
finally
{
if (notifyAfter)
FireChangeNotification();
suppressOnCollectionChanged = false;
}
}
}
/// <summary>
/// Replaces the content of the collection with the supplied items and raises a single <see cref="CollectionChanged"/> event
/// when the operation is complete.
/// </summary>
/// <param name="items">The items to replace the current content.</param>
public void ReplaceContent(IEnumerable<T> items)
{
SuppressChangeNotification();
ClearItems();
AddRange(items);
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (!suppressOnCollectionChanged)
{
#if NoCrossThreadSupport
base.OnCollectionChanged(e);
#else
using (BlockReentrancy())
{
NotifyCollectionChangedEventHandler eventHandler = CollectionChanged;
if (eventHandler == null)
return;
Delegate[] delegates = eventHandler.GetInvocationList();
// Walk the invocation list
foreach (NotifyCollectionChangedEventHandler handler in delegates)
{
DispatcherObject dispatcherObject = handler.Target as DispatcherObject;
// If the subscriber is a DispatcherObject and different thread
if (dispatcherObject != null && !dispatcherObject.CheckAccess())
{
// Invoke handler in the target dispatcher's thread
dispatcherObject.Dispatcher.Invoke(DispatcherPriority.DataBind, handler, this, e);
}
else // Execute handler as is
handler(this, e);
}
}
#endif
}
}
I have tried using a List but I got the same behaviour.
Any ideas?

How to format SQL Server DateTimeOffset and move to Oracle using OracleBulkCopy

I'm trying to move SQL Server DateTimeOffset or Oracle using OracleBulkCopy.
For DateTimeOffset(1) the target data type is Timestamp(1) With Time Zone.
If I do a select of the DateTimeOffset(1) column on SQL Server I receive the following:
2007-05-08 12:35:29.1 +12:15
When I try to move this to Oracle I receive:
ORA-01843: not a valid month
It makes sense and I believe the month needs to first, but If I run INSERT into MyOracleTable values('2007-05-08 12:35:29.1 +12:15') I can insert just fine.
I've tried Converting the datetimeoffset to various formats on the SQL Server side. I receive various errors one being:
ORA-01855: AM/A.M. or PM/P.M. required
The NLS_TIMESTAMP_TZ_FORMAT parameter is:
YYYY-MM-DD HH24:MI:SSXFF TZR
Thank you for your help!
My idea is to create a wrapper for SqlDataReader and do the conversion inside:
using (SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=test;Integrated Security=True;"))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("Select * from table_2", conn))
{
using (SqlDataReader sqlReader = cmd.ExecuteReader())
{
using (ReaderWrapper reader = new ReaderWrapper(sqlReader))
{
using (OracleBulkCopy bulkCopy = new OracleBulkCopy("data source=oracle;user id=user;password=secret", OracleBulkCopyOptions.Default))
{
bulkCopy.DestinationTableName = "tb_date";
bulkCopy.WriteToServer(reader);
}
}
}
}
}
The wrapper itself is bulky, but very simple:
internal sealed class ReaderWrapper : IDataReader
{
#region Fields
private bool _disposed;
private IDataReader _reader;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="ReaderWrapper"/> class.
/// </summary>
/// <param name="reader">The wrapped reader.</param>
public ReaderWrapper(IDataReader reader)
{
this._reader = reader;
}
#endregion
#region Properties
/// <summary>
/// Gets the number of columns in the current row.
/// </summary>
/// <value></value>
/// <returns>
/// When not positioned in a valid recordset, 0; otherwise, the number of columns in the current record. The default is -1.
/// </returns>
public int FieldCount
{
get { return this._reader.FieldCount; }
}
#endregion
#region Indexers
/// <summary>
/// Gets the column located at the specified index.
/// </summary>
/// <param name="i">The zero-based index of the column to get.</param>
/// <returns>The column located at the specified index.</returns>
/// <exception cref="System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="FieldCount"/>.</exception>
public object this[int i]
{
get { return this.GetValue(i); }
}
/// <summary>
/// Gets the column with the specified name.
/// </summary>
/// <param name="name">The name of the column to find.</param>
/// <returns>The column with the specified name.</returns>
/// <exception cref="System.IndexOutOfRangeException">No column with the specified name was found.</exception>
public object this[string name]
{
get { return this._reader[name]; }
}
#endregion
#region Methods
/// <summary>
/// Advances the <see cref="T:System.Data.IDataReader"/> to the next record.
/// </summary>
/// <returns>
/// <see langword="true"/> if there are more rows; otherwise, <see langword="false"/>.
/// </returns>
public bool Read()
{
return this._reader.Read();
}
/// <summary>
/// Return the value of the specified field.
/// </summary>
/// <param name="i">The index of the field to find.</param>
/// <returns>
/// The <see cref="T:System.Object"/> which will contain the field value upon return.
/// </returns>
/// <exception cref="T:System.IndexOutOfRangeException">
/// The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>.
/// </exception>
public object GetValue(int i)
{
object sqlValue = this._reader[i];
DateTimeOffset? dateValue = sqlValue as DateTimeOffset?;
if (dateValue == null)
{
return sqlValue;
}
// Ensure that DateTimeOffset can be converted to Oracle
OracleTimeStampTZ oracleDate = new OracleTimeStampTZ(dateValue.Value.UtcDateTime, dateValue.Value.Offset.ToString());
return oracleDate;
}
/// <summary>
/// Gets the <see cref="T:System.Type" /> information corresponding to the type of <see cref="T:System.Object" /> that would be returned from <see cref="M:System.Data.IDataRecord.GetValue(System.Int32)" />.
/// </summary>
/// <param name="i">The index of the field to find.</param>
/// <returns>
/// The <see cref="T:System.Type" /> information corresponding to the type of <see cref="T:System.Object" /> that would be returned from <see cref="M:System.Data.IDataRecord.GetValue(System.Int32)" />.
/// </returns>
/// <exception cref="NotSupportedException"></exception>
Type IDataRecord.GetFieldType(int i)
{
return this._reader.GetFieldType(i);
}
public int GetOrdinal(string name)
{
return this._reader.GetOrdinal(name);
}
public bool IsDBNull(int i)
{
return this.IsDBNull(i);
}
/// <summary>
/// Closes the <see cref="T:System.Data.IDataReader"/> Object.
/// </summary>
public void Close()
{
this._reader.Dispose();
}
/// <summary>
/// Performs application-defined tasks associated with freeing,
/// releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
if (!this._disposed)
{
this._reader.Dispose();
this._disposed = true;
}
}
#endregion
#region Not Implemented
bool IDataReader.IsClosed
{
get { throw new NotSupportedException(); }
}
void IDataReader.Close()
{
throw new NotSupportedException();
}
int IDataReader.Depth
{
get { throw new NotSupportedException(); }
}
DataTable IDataReader.GetSchemaTable()
{
throw new NotSupportedException();
}
bool IDataReader.NextResult()
{
throw new NotSupportedException();
}
int IDataReader.RecordsAffected
{
get { throw new NotSupportedException(); }
}
bool IDataRecord.GetBoolean(int i)
{
throw new NotSupportedException();
}
byte IDataRecord.GetByte(int i)
{
throw new NotSupportedException();
}
long IDataRecord.GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
{
throw new NotSupportedException();
}
char IDataRecord.GetChar(int i)
{
throw new NotSupportedException();
}
long IDataRecord.GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
{
throw new NotSupportedException();
}
IDataReader IDataRecord.GetData(int i)
{
throw new NotSupportedException();
}
string IDataRecord.GetDataTypeName(int i)
{
throw new NotSupportedException();
}
DateTime IDataRecord.GetDateTime(int i)
{
throw new NotSupportedException();
}
decimal IDataRecord.GetDecimal(int i)
{
throw new NotSupportedException();
}
double IDataRecord.GetDouble(int i)
{
throw new NotSupportedException();
}
float IDataRecord.GetFloat(int i)
{
throw new NotSupportedException();
}
Guid IDataRecord.GetGuid(int i)
{
throw new NotSupportedException();
}
short IDataRecord.GetInt16(int i)
{
throw new NotSupportedException();
}
int IDataRecord.GetInt32(int i)
{
throw new NotSupportedException();
}
long IDataRecord.GetInt64(int i)
{
throw new NotSupportedException();
}
string IDataRecord.GetName(int i)
{
throw new NotSupportedException();
}
string IDataRecord.GetString(int i)
{
throw new NotSupportedException();
}
int IDataRecord.GetValues(object[] values)
{
throw new NotSupportedException();
}
#endregion
The actual conversion is done here:
public object GetValue(int i)
{
object sqlValue = this._reader[i];
DateTimeOffset? dateValue = sqlValue as DateTimeOffset?;
if (dateValue == null)
{
return sqlValue;
}
// Ensure that DateTimeOffset can be converted to Oracle
OracleTimeStampTZ oracleDate = new OracleTimeStampTZ(dateValue.Value.UtcDateTime, dateValue.Value.Offset.ToString());
return oracleDate;
}

Production connectivity issue to WebApi Project using Breeze + Angular

I have implement a project using John Papa's HotTowel example with Breeze & Angular.
I have two application.
App.Web
App.WebApis
In my local environment they work great and running on different ports:
App.Web (localhost:{port1})
App.WebApis ( localhost: 59063)
When I pushed the code out to production, I created two web application in IIS w/ following bindings
App.Web (domain: www.{mydoman}.com, port: 80}
App.WebApis (domain: localhost, port: 59063}
When I run the app, I get the following error:
[OTG Error] Error retrieving data.Metadata query failed for: http://localhost:59063/breeze/Breeze/Metadata; HTTP response status 0 and no message. Likely did not or could not reach server. Is the server running? Error: Metadata query failed for: http://localhost:59063/breeze/Breeze/Metadata; HTTP response status 0 and no message. Likely did not or could not reach server. Is the server running?
Here is what I have done so far:
Under Application_Start() in Global.asax.cs
System.Web.Http.GlobalConfiguration.Configuration.MessageHandlers.Add(new BreezeSimpleCorsHandler());
Here is the BreezeSimpleCorsHandler.cs:
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace Breeze.WebApi
{
/// <summary>
/// Global message handler for CORS support (Development Only)
/// </summary>
/// <remarks>
/// Simple-minded, allow-everything, Web API message handler
/// for CORS (Cross-origin resource sharing)
/// http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
/// Accepts any request for any action from any site
/// Warning: Do not use for production code. Use as inspiration for a
/// solution that is consistent with your security requirements.
/// Code copied with minor changes from
/// http://blog.bittercoder.com/2012/09/09/cors-and-webapi/
/// Install early in Web Api Pipeline,
/// perhaps in Global.asax or BreezeWebApiConfig
/// Set "runaAllManagedModulesForAllRequests" in Web.config for < IIS 8
/// </remarks>
/// <example>
/// // In Global.asax
/// protected void Application_Start()
/// {
/// ...
/// GlobalConfiguration.Configuration.MessageHandlers.Add(new BreezeSimpleCorsHandler());
/// ...
/// }
///
/// // In BreezeWebApiConfig
/// public static void RegisterBreezePreStart() {
/// ...
/// GlobalConfiguration.Configuration.MessageHandlers.Add(new BreezeSimpleCorsHandler());
/// ...
/// }
/// </example>
public class BreezeSimpleCorsHandler : DelegatingHandler
{
const string Origin = "Origin";
const string AccessControlRequestMethod = "Access-Control-Request-Method";
const string AccessControlRequestHeaders = "Access-Control-Request-Headers";
const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";
const string AccessControlAllowCredentials = "Access-Control-Allow-Credentials";
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var isCorsRequest = request.Headers.Contains(Origin);
var isPreflightRequest = request.Method == HttpMethod.Options;
if (isCorsRequest)
{
if (isPreflightRequest)
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Headers.Add(AccessControlAllowOrigin,
request.Headers.GetValues(Origin).First());
var accessControlRequestMethod =
request.Headers.GetValues(AccessControlRequestMethod).FirstOrDefault();
if (accessControlRequestMethod != null)
{
response.Headers.Add(AccessControlAllowMethods, accessControlRequestMethod);
}
var requestedHeaders = string.Join(", ",
request.Headers.GetValues(AccessControlRequestHeaders));
if (!string.IsNullOrEmpty(requestedHeaders))
{
response.Headers.Add(AccessControlAllowHeaders, requestedHeaders);
}
response.Headers.Add(AccessControlAllowCredentials, "true");
var tcs = new TaskCompletionSource<HttpResponseMessage>();
tcs.SetResult(response);
return tcs.Task;
}
return base.SendAsync(request, cancellationToken).ContinueWith(t =>
{
var resp = t.Result;
resp.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());
resp.Headers.Add(AccessControlAllowCredentials, "true");
return resp;
});
}
return base.SendAsync(request, cancellationToken);
}
}
}
I have tried, putting the code that's in Global.asax.cs in the BreezeWebApiConfig.cs that does not work.
I have tried putting this in web.config:
<system.webServer>
<handlers>
</handlers>
<httpProtocol>
<customHeaders>
<!-- Adding the following custom HttpHeader will help prevent CORS from stopping the Request-->
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
Please advice on what I am missing in the WebApi project.

How to download shared image in Mirror API using .NET

I have subscribed timeline notification in my Glassware app. I got notification when user shared an image with Glassware contest. Now I need to download that image to my Glassware application to do the processing.
Notification notification =
new NewtonsoftJsonSerializer().Deserialize<Notification>(Request.InputStream);
String userId = notification.UserToken;
MirrorService service = new MirrorService(new BaseClientService.Initializer()
{
Authenticator = Utils.GetAuthenticatorFromState(Utils.GetStoredCredentials(userId))
});
if (notification.Collection == "timeline")
{
foreach (UserAction action in notification.UserActions)
{
if (action.Type == "SHARE")
{
TimelineItem item = service.Timeline.Get(notification.ItemId).Fetch();
//i have to download content here.
break;
}
else
{
Console.WriteLine(
"I don't know what to do with this notification: " + action.ToString());
}
}
}
Downloading an attachment is described in the reference guide:
using System;
using Google.Apis.Mirror.v1;
using Google.Apis.Mirror.v1.Data;
using System.Net;
using System.IO;
public class MyClass {
// ...
/// <summary>
/// Print an attachment's metadata.
/// </summary>
/// <param name="service">Authorized Mirror service.</param>
/// <param name="itemId">ID of the timeline item the attachment belongs to.</param>
/// <param name="attachmentId">ID of the attachment to print metadata for.</param>
public static void PrintAttachmentMetadata(
MirrorService service, String itemId, String attachmentId) {
try {
Attachment attachment = service.Timeline.Attachments.Get(itemId, attachmentId).Fetch();
Console.WriteLine("Attachment content type: " + attachment.ContentType);
Console.WriteLine("Attachment content URL: " + attachment.ContentUrl);
} catch (Exception e) {
Console.WriteLine("An error occurred: " + e.Message);
}
}
/// <summary>
/// Download a timeline items's attachment.
/// </summary>
/// <param name="service">Authorized Mirror service.</param>
/// <param name="attachment">Attachment to download content for.</param>
/// <returns>Attachment's content if successful, null otherwise.</returns>
public static System.IO.Stream DownloadAttachment(
MirrorService service, Attachment attachment) {
try {
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
new Uri(attachment.ContentUrl));
service.Authenticator.ApplyAuthenticationToRequest(request);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK) {
return response.GetResponseStream();
} else {
Console.WriteLine(
"An error occurred: " + response.StatusDescription);
return null;
}
} catch (Exception e) {
Console.WriteLine("An error occurred: " + e.Message);
return null;
}
}
// ...
}

Async CTP for a PostSubmitter with Cancelltion Support (CancellationTokenSource) and Progress report

fellow devs!
I have a class for posting to website using a POST or GET and read the response. It's all Async now and doesn't cause the UI to hang.
I need to upgrade it to handle cancellation now. All the Async methods being used are NOT accepting the cancellation token. I need to understand why and what are my alternatives. If its possible, should i create the CancellationTokenSource object within the class or parametrize it from the UI?
Secondly, I need to expose the progress of the PostData() method. How would I do that?
The class:
using System;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Windows.Forms;
using System.Collections.Generic;
using RESTClient.Core.UploadFile;
using System.Threading;
namespace RESTClient.Core {
/// <summary>
/// Submits post data to a url.
/// </summary>
public class PostSubmitter {
#region Backing Store
private string _URL = string.Empty;
private NameValueCollection _PostValues = new NameValueCollection();
private PostTypeEnum _PostType = PostTypeEnum.GET;
#endregion
#region Constructors
/// <summary>
/// Default constructor.
/// </summary>
public PostSubmitter() {
}
/// <summary>
/// Constructor that accepts a url as a parameter
/// </summary>
/// <param name="url">The url where the post will be submitted to.</param>
public PostSubmitter(string url)
: this() {
_URL = url;
}
/// <summary>
/// Constructor allowing the setting of the url and items to post.
/// </summary>
/// <param name="url">the url for the post.</param>
/// <param name="values">The values for the post.</param>
public PostSubmitter(string url, NameValueCollection values)
: this(url) {
_PostValues = values;
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the url to submit the post to.
/// </summary>
public string Url {
get {
return _URL;
}
set {
_URL = value;
}
}
/// <summary>
/// Gets or sets the name value collection of items to post.
/// </summary>
public NameValueCollection PostItems {
get {
return _PostValues;
}
set {
_PostValues = value;
}
}
/// <summary>
/// Gets or sets the type of action to perform against the url.
/// </summary>
public PostTypeEnum Type {
get {
return _PostType;
}
set {
_PostType = value;
}
}
#endregion
/// <summary>
/// Posts the supplied data to specified url.
/// </summary>
/// <returns>a string containing the result of the post.</returns>
public async Task<String> Post() {
StringBuilder parameters = new StringBuilder();
for (int i = 0; i < _PostValues.Count; i++) {
EncodeAndAddItem(ref parameters, _PostValues.GetKey(i), _PostValues[i]);
}
string result = await PostData(_URL, parameters.ToString());
return result;
}
/// <summary>
/// Posts the supplied data to specified url.
/// </summary>
/// <param name="url">The url to post to.</param>
/// <returns>a string containing the result of the post.</returns>
public async Task<String> Post(string url) {
_URL = url;
return await this.Post();
}
/// <summary>
/// Posts the supplied data to specified url.
/// </summary>
/// <param name="url">The url to post to.</param>
/// <param name="values">The values to post.</param>
/// <returns>a string containing the result of the post.</returns>
public async Task<String> Post(string url, NameValueCollection values) {
_PostValues = values;
return await this.Post(url);
}
/// <summary>
/// Posts data to a specified url. Note that this assumes that you have already url encoded the post data.
/// </summary>
/// <param name="postData">The data to post.</param>
/// <param name="url">the url to post to.</param>
/// <returns>Returns the result of the post.</returns>
private async Task<String> PostData(string url, string postData) {
HttpWebRequest request = null;
if (_PostType == PostTypeEnum.POST) {
Uri uri = new Uri(url);
request = WebRequest.Create(uri) as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postData.Length;
using (Stream writeStream = await request.GetRequestStreamAsync()) {
UTF8Encoding encoding = new UTF8Encoding();
byte[] bytes = encoding.GetBytes(postData);
writeStream.Write(bytes, 0, bytes.Length);
}
}
else {
Uri uri = new Uri(url + "?" + postData);
request = WebRequest.Create(uri) as HttpWebRequest;
request.Method = "GET";
}
using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync()) {
using (Stream responseStream = response.GetResponseStream()) {
using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8)) {
return await readStream.ReadToEndAsync();
}
}
}
}
/// <summary>
/// Encodes an item and ads it to the string.
/// </summary>
/// <param name="baseRequest">The previously encoded data.</param>
/// <param name="dataItem">The data to encode.</param>
/// <returns>A string containing the old data and the previously encoded data.</returns>
private void EncodeAndAddItem(ref StringBuilder baseRequest, string key, string dataItem) {
if (baseRequest == null) {
baseRequest = new StringBuilder();
}
if (baseRequest.Length != 0) {
baseRequest.Append("&");
}
baseRequest.Append(key);
baseRequest.Append("=");
baseRequest.Append(HttpUtility.UrlEncode(dataItem));
}
public async void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc) {
//log.Debug(string.Format("Uploading {0} to {1}", file, url));
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest wr = WebRequest.Create(url) as HttpWebRequest;
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = CredentialCache.DefaultCredentials;
Stream rs = await wr.GetRequestStreamAsync();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
foreach (string key in nvc.Keys) {
await rs.WriteAsync(boundarybytes, 0, boundarybytes.Length);
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = Encoding.UTF8.GetBytes(formitem);
await rs.WriteAsync(formitembytes, 0, formitembytes.Length);
}
await rs.WriteAsync(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, file, contentType);
byte[] headerbytes = Encoding.UTF8.GetBytes(header);
rs.WriteAsync(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) != 0) {
await rs.WriteAsync(buffer, 0, bytesRead);
}
fileStream.Close();
byte[] trailer = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
await rs.WriteAsync(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try {
wresp = await wr.GetResponseAsync();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
//log.Debug(string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd()));
}
catch (Exception ex) {
//log.Error("Error uploading file", ex);
if (wresp != null) {
wresp.Close();
wresp = null;
}
}
finally {
wr = null;
}
/**
NameValueCollection nvc = new NameValueCollection();
nvc.Add("id", "TTR");
nvc.Add("btn-submit-photo", "Upload");
HttpUploadFile("http://your.server.com/upload", #"C:\test\test.jpg", "file", "image/jpeg", nvc);
**/
}
public async Task<String> ExecutePostRequest(Uri url, Dictionary<string, string> postData, FileInfo fileToUpload, string fileMimeType, string fileFormKey) {
HttpWebRequest request = WebRequest.Create(url.AbsoluteUri) as HttpWebRequest;
request.Method = "POST";
request.KeepAlive = true;
String boundary = Utility.CreateFormDataBoundary();
request.ContentType = "multipart/form-data; boundary=" + boundary;
Stream requestStream = await request.GetRequestStreamAsync();
postData.WriteMultipartFormData(requestStream, boundary);
if (fileToUpload != null) {
//TODO: Need async here...
fileToUpload.WriteMultipartFormData(requestStream, boundary, fileMimeType, fileFormKey);
}
byte[] endBytes = Encoding.UTF8.GetBytes("--" + boundary + "--");
await requestStream.WriteAsync(endBytes, 0, endBytes.Length);
requestStream.Close();
using (WebResponse response = await request.GetResponseAsync()) {
using (StreamReader reader = new StreamReader(response.GetResponseStream())) {
return await reader.ReadToEndAsync();
}
}
}
}
}
Note: There are three method in the end that are for file uploading. I still need to figure then out and before I do, I need to understand the Cancellation and Progress reporting.
Related question Async CTP for a PostSubmitter
Any help would be much appreciated.
You support progress and cancellation by taking IProgress<T> and CancellationToken parameters.
For cancellation, periodically check whether cancellation has been requested by calling CancellationToken.ThrowIfCancellationRequested. For more information, see Cancellation on MSDN.
For progress, you need to first decide what kind of "progress" makes sense. E.g., if "progress" is just a number of bytes transferred, then you can use IProgress<int>. Once you've decided on your progress type, then call IProgress<T>.Report to report the progress. There are two things to be aware of for IProgress<T>:
The IProgress<T> parameter may be null.
IProgress<T>.Report operates asynchronously. This means that you must either: A) use a value type for T in IProgress<T>; B) perform a deep copy of every T object passed to IProgress<T>.Report; or C) create a new T object each time you call IProgress<T>.Report.

Resources