I have a console application which needs to connect to SQL Reporting Services on SQL Server Express 2012.
All the exporting logic should be implemented in a separate dll, and the paths should be dynamic (I have loop through various settings for various servers/reports and export them to Excel one by one).
I tried to follow these tutorials:
http://www.aspose.com/docs/display/wordsreportingservices/Rendering+Reports+Programmatically
http://blogs.msdn.com/b/selvar/archive/2010/12/13/accessing-the-reportexecutionservice-render-method-when-reporting-service-2008-r2-is-in-forms-based-authentication.aspx
Basically, I added web references:
http://localhost:80/ReportServer_SQLEXPRESS12/ReportExecution2005.asmx
and
http://localhost:80/ReportServer_SQLEXPRESS12/ReportService2010.asmx
to my dll. Looks good so far, except those nasty app.config settings (I'll have to adjust them dynamically later).
Then I tried to do as in the example:
// Create Web service proxies.
ReportingService2010.ReportingService2010 rs = new ReportingService2010.ReportingService2010();
ReportExecutionService.ReportExecutionService rsExec = new ReportExecutionService.ReportExecutionService();
and got some troubles:
Error 76 The type or namespace name 'ReportExecutionService' does not exist in the namespace 'MyDllNamespace.ReportExecutionService' (are you missing an assembly reference?)
Error 74 The type or namespace name 'ReportingService2010' does not exist in the namespace 'MyDllNamespace.ReportingService2010' (are you missing an assembly reference?)
Now where do I go next, how do I use the Reporting Services API, if I cannot even create a proxy object? Or should I better use ServerReport class form the Winforms ReportViewer instead of these web references?
Even one of Microsoft examples is using ReportViewer in a console application, but it seems a bit awkward to import Winforms in a console app.
I hope the following will help (extract of pertinent parts of code)
using (ZUtilities.SSRS.Report report = new ZUtilities.SSRS.Report {
ReportServerPath = VParameter.GetValue("SSRS_WebServiceUrl", _repo.Parameters).ToString(),
Format = rformat,
ReportPath = "some_path_on_ssrs_server"
}) {
report.Params.Add("Id", id.ToString());
report.Credentials = nwc;
MemoryStream ms = new MemoryStream();
report.Render().CopyTo(ms);
FileContentResult fsr = new FileContentResult(ms.ToArray(), rctype);
fsr.FileDownloadName = String.Format("EPV-{0}-{1:yyyyMMdd}.{2}", epv.ExternalReference, DateTime.Now, fext);
ms.Close();
return fsr;
}
with the following (be carefull to the stream management)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
namespace ZUtilities.SSRS {
public enum ReportFormats {
Html = 1,
MHtml,
Pdf,
Xlsx,
Docx
}
public class ReportFormat {
static ReportFormat() {
Html = new ReportFormat { Code = ReportFormats.Html, Instruction = "HTML4.0" };
MHtml = new ReportFormat { Code = ReportFormats.MHtml, Instruction = "MHTML" };
Pdf = new ReportFormat { Code = ReportFormats.Pdf, Instruction = "PDF" };
Xlsx = new ReportFormat { Code = ReportFormats.Xlsx, Instruction = "EXCELOPENXML" };
Docx = new ReportFormat { Code = ReportFormats.Docx, Instruction = "WORDOPENXML" };
}
private ReportFormat() {
}
public ReportFormats Code { get; set; }
public String Instruction { get; set; }
public static ReportFormat Html { get; private set; }
public static ReportFormat MHtml { get; private set; }
public static ReportFormat Pdf { get; private set; }
public static ReportFormat Xlsx { get; private set; }
public static ReportFormat Docx { get; private set; }
public static ReportFormat ByCode(ReportFormats code) {
switch (code) {
case ReportFormats.Html: return Html;
case ReportFormats.MHtml: return Html; //<<======================
case ReportFormats.Pdf: return Pdf;
case ReportFormats.Xlsx: return Xlsx;
case ReportFormats.Docx: return Docx;
default : return null;
}
}
}
public class Report : IDisposable {
private HttpWebRequest _httpWReq;
private WebResponse _httpWResp;
public Report() {
_httpWReq = null;
_httpWResp = null;
Format = ReportFormats.Html;
Params = new Dictionary<String, String>();
}
public Dictionary<String, String> Params { get; set; }
public String ReportServerPath { get; set; }
public String ReportPath { get; set; }
public ReportFormats Format { get; set; }
public NetworkCredential Credentials { get; set; }
//public String PostData { get { return String.Format("rs:Command=Render&rs:Format={0}", ReportFormat.ByCode(Format).Instruction); } }
public String PostData { get {
StringBuilder sb = new StringBuilder(1024);
sb.AppendFormat("rs:Command=Render&rs:Format={0}", ReportFormat.ByCode(Format).Instruction);
if (Format == ReportFormats.Html) {
sb.Append("&rc:Toolbar=false");
}
foreach (var kv in Params) {
sb.AppendFormat("&{0}={1}", kv.Key, kv.Value);
}
return sb.ToString();
} }
public String ReportFullPath { get { return ReportServerPath + "?/" + ReportPath; } }
public Stream Render() {
_httpWReq = (HttpWebRequest)HttpWebRequest.Create(ReportFullPath);
_httpWReq.Method = "POST";
if (Credentials != null)
_httpWReq.Credentials = Credentials;
byte[] byteArray = Encoding.UTF8.GetBytes(PostData);
_httpWReq.ContentType = "application/x-www-form-urlencoded";
_httpWReq.ContentLength = byteArray.Length;
Stream dataStream = _httpWReq.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
if (_httpWResp != null )
_httpWResp.Close();
_httpWResp = _httpWReq.GetResponse();
return _httpWResp.GetResponseStream();
}
public void RenderTo(String fileName) {
Stream receiveStream = Render();
Stream ds = File.Open(fileName, FileMode.Create);
receiveStream.CopyTo(ds);
ds.Close();
receiveStream.Close();
}
public void Dispose() {
if (_httpWResp != null) {
_httpWResp.Close();
_httpWResp = null;
}
if (_httpWReq != null) {
_httpWReq = null;
}
}
}
}
Related
I have a .xlsx file, which contains the first column projectname, second column description.
I want to create a console app for create projects from azureProjects.xlsx file using Azure DevOps Rest API. I already implement the code below, but I can't understand how to read from .xlsx file and implement the code. Can you have a solution to help me?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace WorkItemTest
{
class AzureAdmin
{
private readonly Uri uri;
private readonly string personalAccessToken;
public AzureAdmin(string orgName, string personalAccessToken)
{
this.uri = new Uri("https://dev.azure.com/" + orgName);
this.personalAccessToken = personalAccessToken;
}
public async Task<bool> createProject()
{
try
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
Encoding.ASCII.GetBytes(
string.Format("{0}:{1}", "", personalAccessToken))));
var req = new Root
{
name = "test3",
description = "test about smthng",
visibility = 0,
capabilities = new Capabilities
{
versioncontrol = new Versioncontrol {sourceControlType = "Git"},
processTemplate = new ProcessTemplate
{
templateTypeId = "b8a3a935-7e91-48b8-a94c-606d37c3e9f2"
}
}
};
var result = await client.PostAsJsonAsync($"{uri}/_apis/projects?api-version=5.1", req); //
Console.WriteLine(result.StatusCode);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
return true;
}
public class Versioncontrol
{
public string sourceControlType { get; set; }
}
public class ProcessTemplate
{
public string templateTypeId { get; set; }
}
public class Capabilities
{
public Versioncontrol versioncontrol { get; set; }
public ProcessTemplate processTemplate { get; set; }
}
public class Root
{
public string name { get; set; }
public string description { get; set; }
public int visibility { get; set; }
public Capabilities capabilities { get; set; }
}
}
}
You have implemented how to create a team project in DevOps, what you need is reading the project names from .xlsx file. This is not implemented via Azure Devops API, you just need to get help from Excel side to get how to read data from .xlsx file via api.
Check the following link to see whether it helps you:
https://learn.microsoft.com/en-us/troubleshoot/dotnet/csharp/query-excel-data-aspx-page
I have found many different solutions with OAuth and either with some libraries or with pure requests (https://github.com/googlesamples/oauth-apps-for-windows).
However, none of the solutions looks like the one that I really need. Currently, my application uses its own database for users to log in using WCF service request (with username and password). However, all users have their domain e-mail created with Google accounts, so I want to add another button "Sign In with Google", which will just make sure that user can also login with his Google e-mail-password pair. I don't need a returned token for the further use etc.
What is the simplest way to achieve this functionality in WPF/C# desktop application?
Here is a self-sufficient, 3rd party-free, WPF sample that does Google auth (it could be easily converted to winforms as well).
If you run it you won't be logged and the app will show you a button. If you click that button, an embedded webbrowser control will run though the Google auth.
Once you are authenticated, the app will just display your name as returned by Google.
Note it's based on official Google's sample here: https://github.com/googlesamples/oauth-apps-for-windows but it uses an embedded browser instead of spawning an external one (and few other differences).
XAML code:
<Window x:Class="GoogleAuth.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="750" Width="525">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="btv" />
</Window.Resources>
<Grid>
<DockPanel Visibility="{Binding State.IsSigned, Converter={StaticResource btv}}">
<Label>You are signed as:</Label>
<Label Content="{Binding State.Token.Name}" />
</DockPanel>
<Grid Visibility="{Binding State.IsNotSigned, Converter={StaticResource btv}}">
<Grid.RowDefinitions>
<RowDefinition Height="23" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Click="Button_Click">Click to Sign In</Button>
<WebBrowser Grid.Row="1" x:Name="Wb" Height="Auto" />
</Grid>
</Grid>
</Window>
C# code:
using System;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
namespace GoogleAuth
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
State = new OAuthState();
DataContext = this;
}
public OAuthState State { get; }
private void Button_Click(object sender, RoutedEventArgs e)
{
var thread = new Thread(HandleRedirect);
thread.Start();
}
private async void HandleRedirect()
{
State.Token = null;
// for example, let's pretend I want also want to have access to WebAlbums
var scopes = new string[] { "https://picasaweb.google.com/data/" };
var request = OAuthRequest.BuildLoopbackRequest(scopes);
var listener = new HttpListener();
listener.Prefixes.Add(request.RedirectUri);
listener.Start();
// note: add a reference to System.Windows.Presentation and a 'using System.Windows.Threading' for this to compile
await Dispatcher.BeginInvoke(() =>
{
Wb.Navigate(request.AuthorizationRequestUri);
});
// here, we'll wait for redirection from our hosted webbrowser
var context = await listener.GetContextAsync();
// browser has navigated to our small http servern answer anything here
string html = string.Format("<html><body></body></html>");
var buffer = Encoding.UTF8.GetBytes(html);
context.Response.ContentLength64 = buffer.Length;
var stream = context.Response.OutputStream;
var responseTask = stream.WriteAsync(buffer, 0, buffer.Length).ContinueWith((task) =>
{
stream.Close();
listener.Stop();
});
string error = context.Request.QueryString["error"];
if (error != null)
return;
string state = context.Request.QueryString["state"];
if (state != request.State)
return;
string code = context.Request.QueryString["code"];
State.Token = request.ExchangeCodeForAccessToken(code);
}
}
// state model
public class OAuthState : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private OAuthToken _token;
public OAuthToken Token
{
get => _token;
set
{
if (_token == value)
return;
_token = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Token)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsSigned)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsNotSigned)));
}
}
public bool IsSigned => Token != null && Token.ExpirationDate > DateTime.Now;
public bool IsNotSigned => !IsSigned;
}
// This is a sample. Fille information (email, etc.) can depend on scopes
[DataContract]
public class OAuthToken
{
[DataMember(Name = "access_token")]
public string AccessToken { get; set; }
[DataMember(Name = "token_type")]
public string TokenType { get; set; }
[DataMember(Name = "expires_in")]
public int ExpiresIn { get; set; }
[DataMember(Name = "refresh_token")]
public string RefreshToken { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Email { get; set; }
[DataMember]
public string Picture { get; set; }
[DataMember]
public string Locale { get; set; }
[DataMember]
public string FamilyName { get; set; }
[DataMember]
public string GivenName { get; set; }
[DataMember]
public string Id { get; set; }
[DataMember]
public string Profile { get; set; }
[DataMember]
public string[] Scopes { get; set; }
// not from google's response, but we store this
public DateTime ExpirationDate { get; set; }
}
// largely inspired from
// https://github.com/googlesamples/oauth-apps-for-windows
public sealed class OAuthRequest
{
// TODO: this is a sample, please change these two, use your own!
private const string ClientId = "581786658708-elflankerquo1a6vsckabbhn25hclla0.apps.googleusercontent.com";
private const string ClientSecret = "3f6NggMbPtrmIBpgx-MK2xXK";
private const string AuthorizationEndpoint = "https://accounts.google.com/o/oauth2/v2/auth";
private const string TokenEndpoint = "https://www.googleapis.com/oauth2/v4/token";
private const string UserInfoEndpoint = "https://www.googleapis.com/oauth2/v3/userinfo";
private OAuthRequest()
{
}
public string AuthorizationRequestUri { get; private set; }
public string State { get; private set; }
public string RedirectUri { get; private set; }
public string CodeVerifier { get; private set; }
public string[] Scopes { get; private set; }
// https://developers.google.com/identity/protocols/OAuth2InstalledApp
public static OAuthRequest BuildLoopbackRequest(params string[] scopes)
{
var request = new OAuthRequest
{
CodeVerifier = RandomDataBase64Url(32),
Scopes = scopes
};
string codeChallenge = Base64UrlEncodeNoPadding(Sha256(request.CodeVerifier));
const string codeChallengeMethod = "S256";
string scope = BuildScopes(scopes);
request.RedirectUri = string.Format("http://{0}:{1}/", IPAddress.Loopback, GetRandomUnusedPort());
request.State = RandomDataBase64Url(32);
request.AuthorizationRequestUri = string.Format("{0}?response_type=code&scope=openid%20profile{6}&redirect_uri={1}&client_id={2}&state={3}&code_challenge={4}&code_challenge_method={5}",
AuthorizationEndpoint,
Uri.EscapeDataString(request.RedirectUri),
ClientId,
request.State,
codeChallenge,
codeChallengeMethod,
scope);
return request;
}
// https://developers.google.com/identity/protocols/OAuth2InstalledApp Step 5: Exchange authorization code for refresh and access tokens
public OAuthToken ExchangeCodeForAccessToken(string code)
{
if (code == null)
throw new ArgumentNullException(nameof(code));
string tokenRequestBody = string.Format("code={0}&redirect_uri={1}&client_id={2}&code_verifier={3}&client_secret={4}&scope=&grant_type=authorization_code",
code,
Uri.EscapeDataString(RedirectUri),
ClientId,
CodeVerifier,
ClientSecret
);
return TokenRequest(tokenRequestBody, Scopes);
}
// this is not used in this sample, but can be used to refresh a token from an old one
// https://developers.google.com/identity/protocols/OAuth2InstalledApp Refreshing an access token
public OAuthToken Refresh(OAuthToken oldToken)
{
if (oldToken == null)
throw new ArgumentNullException(nameof(oldToken));
string tokenRequestBody = string.Format("refresh_token={0}&client_id={1}&client_secret={2}&grant_type=refresh_token",
oldToken.RefreshToken,
ClientId,
ClientSecret
);
return TokenRequest(tokenRequestBody, oldToken.Scopes);
}
private static T Deserialize<T>(string json)
{
if (string.IsNullOrWhiteSpace(json))
return default(T);
return Deserialize<T>(Encoding.UTF8.GetBytes(json));
}
private static T Deserialize<T>(byte[] json)
{
if (json == null || json.Length == 0)
return default(T);
using (var ms = new MemoryStream(json))
{
return Deserialize<T>(ms);
}
}
private static T Deserialize<T>(Stream json)
{
if (json == null)
return default(T);
var ser = CreateSerializer(typeof(T));
return (T)ser.ReadObject(json);
}
private static DataContractJsonSerializer CreateSerializer(Type type)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
var settings = new DataContractJsonSerializerSettings
{
DateTimeFormat = new DateTimeFormat("yyyy-MM-dd'T'HH:mm:ss.fffK")
};
return new DataContractJsonSerializer(type, settings);
}
// https://stackoverflow.com/questions/223063/how-can-i-create-an-httplistener-class-on-a-random-port-in-c/
private static int GetRandomUnusedPort()
{
var listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
listener.Stop();
return port;
}
private static string RandomDataBase64Url(int length)
{
using (var rng = new RNGCryptoServiceProvider())
{
var bytes = new byte[length];
rng.GetBytes(bytes);
return Base64UrlEncodeNoPadding(bytes);
}
}
private static byte[] Sha256(string text)
{
using (var sha256 = new SHA256Managed())
{
return sha256.ComputeHash(Encoding.ASCII.GetBytes(text));
}
}
private static string Base64UrlEncodeNoPadding(byte[] buffer)
{
string b64 = Convert.ToBase64String(buffer);
// converts base64 to base64url.
b64 = b64.Replace('+', '-');
b64 = b64.Replace('/', '_');
// strips padding.
b64 = b64.Replace("=", "");
return b64;
}
private static OAuthToken TokenRequest(string tokenRequestBody, string[] scopes)
{
var request = (HttpWebRequest)WebRequest.Create(TokenEndpoint);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
byte[] bytes = Encoding.ASCII.GetBytes(tokenRequestBody);
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
var response = request.GetResponse();
using (var responseStream = response.GetResponseStream())
{
var token = Deserialize<OAuthToken>(responseStream);
token.ExpirationDate = DateTime.Now + new TimeSpan(0, 0, token.ExpiresIn);
var user = GetUserInfo(token.AccessToken);
token.Name = user.Name;
token.Picture = user.Picture;
token.Email = user.Email;
token.Locale = user.Locale;
token.FamilyName = user.FamilyName;
token.GivenName = user.GivenName;
token.Id = user.Id;
token.Profile = user.Profile;
token.Scopes = scopes;
return token;
}
}
private static UserInfo GetUserInfo(string accessToken)
{
var request = (HttpWebRequest)WebRequest.Create(UserInfoEndpoint);
request.Method = "GET";
request.Headers.Add(string.Format("Authorization: Bearer {0}", accessToken));
var response = request.GetResponse();
using (var stream = response.GetResponseStream())
{
return Deserialize<UserInfo>(stream);
}
}
private static string BuildScopes(string[] scopes)
{
string scope = null;
if (scopes != null)
{
foreach (var sc in scopes)
{
scope += "%20" + Uri.EscapeDataString(sc);
}
}
return scope;
}
// https://developers.google.com/+/web/api/rest/openidconnect/getOpenIdConnect
[DataContract]
private class UserInfo
{
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "kind")]
public string Kind { get; set; }
[DataMember(Name = "email")]
public string Email { get; set; }
[DataMember(Name = "picture")]
public string Picture { get; set; }
[DataMember(Name = "locale")]
public string Locale { get; set; }
[DataMember(Name = "family_name")]
public string FamilyName { get; set; }
[DataMember(Name = "given_name")]
public string GivenName { get; set; }
[DataMember(Name = "sub")]
public string Id { get; set; }
[DataMember(Name = "profile")]
public string Profile { get; set; }
[DataMember(Name = "gender")]
public string Gender { get; set; }
}
}
}
This code uses an embedded Internet Explorer control, but since Google doesn't support old Internet Explorer versions, it's likely that you also need to add some code to play with IE's compatibility features as described here for example: https://stackoverflow.com/a/28626667/403671
You can put that code in App.xaml.cs, like this:
public partial class App : Application
{
public App()
{
// use code from here: https://stackoverflow.com/a/28626667/403671
SetWebBrowserFeatures();
}
}
Note what the webbrowser will display depends entirely on Google, and it can considerably vary depending on the environment like cookies, language, etc.
I think you are missing the point on what the OAuth is, start by reading this and here is a simple description of the flow.
which will just make sure that user can also login with his Google e-mail-password pair, I don't need a returned token for the further use
There is no api for user/pass validation, and the token is the whole point of the OAuth. A user with existing email should be able to login if indeed you registered your application with google. Also i see no point in prior validation of user/pass, just add the button.
I am working on upgrading a .NET application without changing its functionality. What I did so far is:
upgrading from mvc 2 to mvc 4
upgrading from framework 3.5 to 4.0
using visual studio 2015 instead of 2010
upgrading the custom made utilities and mvc the same way
Right now I am stuck at the pdf conversion in the custom utilities dll. The error I get is in the image below. It says:
ExportHtmlToPdfBytes failed for url http://localhost:4984/Rijopdracht.mvc/Print/861175: Conversion error: WebKit Navigation timeout.
Error message.
The link is available and accessible behind a proxy. The method ExportHtmlToPdfBytes looks like this:
public byte[] ExportHtmlToPdfBytes(string url)
{
try
{
PdfConverter pdfConverter = CreatePdfConvertor();
byte[] bytes = pdfConverter.GetPdfBytesFromUrl(url);
return bytes;
}
catch (Exception ex)
{
throw new WrapperException(ex, "ExportHtmlToPdfBytes failed for url {0}:", url);
}
}
During debugging I discovered that the program breaks when it calls the function GetPdfBytesFromUrl. After the program breaks, the proxy user I use to access the url, gets blocked. I found out that a user gets blocked if and only if the password has been typed wrong 6 or more times.
I triple checked the username and password that came from the appsettings, and they are correct. Can somebody tell me what is going on and how to solve this?
The complete class PdfUtilities where this function comes from is:
using ExpertPdf.HtmlToPdf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Jumbo.Utilities
{
public class PdfUtilities
{
public PdfUtilities() {
FooterText = String.Empty;
FitWidth = false;
LeftMargin = 5;
RightMargin = 5;
TopMargin = 5;
BottomMargin = 5;
PdfCompressionLevel = PdfCompressionLevel.Normal;
JpegCompressionLevel = 10;
}
public string FooterText { get; set; }
public string AuthenticationUsername { get; set; }
public string AuthenticationPassword { get; set; }
public bool FitWidth { get; set; }
public string BaseUrl { get; set; }
public int LeftMargin { get; set; }
public int RightMargin { get; set; }
public int TopMargin { get; set; }
public int BottomMargin { get; set; }
public int JpegCompressionLevel { get; set; }
public PdfCompressionLevel PdfCompressionLevel { get; set; }
private PdfConverter CreatePdfConvertor()
{
PdfConverter pdfConverter = new PdfConverter();
pdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
pdfConverter.PdfDocumentOptions.PdfCompressionLevel = PdfCompressionLevel;
pdfConverter.PdfDocumentOptions.PdfPageOrientation = PDFPageOrientation.Landscape;
pdfConverter.PdfDocumentOptions.LiveUrlsEnabled = false;
pdfConverter.PdfDocumentOptions.ShowHeader = true;
pdfConverter.PdfDocumentOptions.ShowFooter = true;
pdfConverter.PdfDocumentOptions.LeftMargin = LeftMargin;
pdfConverter.PdfDocumentOptions.RightMargin = RightMargin;
pdfConverter.PdfDocumentOptions.TopMargin = TopMargin;
pdfConverter.PdfDocumentOptions.BottomMargin = BottomMargin;
pdfConverter.PdfDocumentOptions.GenerateSelectablePdf = true;
pdfConverter.PdfDocumentOptions.EmbedFonts = true;
pdfConverter.PdfDocumentOptions.JpegCompressionLevel = JpegCompressionLevel;
if (FitWidth)
{
pdfConverter.PageWidth = 0;
pdfConverter.PdfDocumentOptions.FitWidth = true;
pdfConverter.PdfDocumentOptions.StretchToFit = true;
}
else
pdfConverter.PdfDocumentOptions.FitWidth = false;
//pdfConverter.PageWidth = 0;
pdfConverter.PdfDocumentOptions.ShowHeader = false;
pdfConverter.PdfFooterOptions.FooterTextColor = System.Drawing.Color.Black;
pdfConverter.PdfFooterOptions.DrawFooterLine = false;
pdfConverter.PdfFooterOptions.PageNumberText = "Page";
pdfConverter.PdfFooterOptions.ShowPageNumber = true;
pdfConverter.PdfFooterOptions.FooterText = FooterText;
if (!string.IsNullOrEmpty(AuthenticationUsername) && !string.IsNullOrEmpty(AuthenticationPassword))
{
pdfConverter.AuthenticationOptions.Username = AuthenticationUsername;
pdfConverter.AuthenticationOptions.Password = AuthenticationPassword;
}
else
{
string username = SettingsUtilities.GetSetting<string>(GenericConstants.AS_PROXY_USERNAME, null);
if (!String.IsNullOrEmpty(username))
{
string password = SettingsUtilities.GetSetting<string>(GenericConstants.AS_PROXY_PASSWORD, null);
pdfConverter.AuthenticationOptions.Username = username;
pdfConverter.AuthenticationOptions.Password = password;
}
}
pdfConverter.LicenseKey = "tZ6HlY2Vh4WBg5WDm4WVhoSbhIebjIyMjA==";
return pdfConverter;
}
public byte[] ExportHtmlToPdfBytes(string url)
{
try
{
PdfConverter pdfConverter = CreatePdfConvertor();
byte[] bytes = pdfConverter.GetPdfBytesFromUrl(url);
return bytes;
}
catch (Exception ex)
{
throw new WrapperException(ex, "ExportHtmlToPdfBytes failed for url {0}:", url);
}
}
public byte[] ExportHtmlStringToPdfBytes(string html)
{
PdfConverter pdfConverter = CreatePdfConvertor();
byte[] bytes;
if (BaseUrl == null)
bytes = pdfConverter.GetPdfBytesFromHtmlString(html);
else
bytes = pdfConverter.GetPdfBytesFromHtmlString(html, BaseUrl);
return bytes;
}
public void SaveHtmlToPdf(string url, string saveLocation)
{
Logging.LogVerboseCaller(Logging.Cat.Utilities, "Start export to htm for " + url);
byte[] contents = ExportHtmlToPdfBytes(url);
Logging.LogVerboseCaller(Logging.Cat.Utilities, "End export. Start save to " + saveLocation);
FileUtilities.SaveFile(saveLocation, contents);
Logging.LogVerboseCaller(Logging.Cat.Utilities, "End save");
}
}
}
A colleague of mine was able to solve it.
First of all: if we needed the proxy, we shouldn't use the AuthenticationOptions. I believe these are meant to login with your ExpertPDF account. There are proxy attributes for the PdfConverter class that could be used for that.
But, that wasn't the problem. My problem was that I used a license for an earlier version. The error wasn't clear on this, but it was an invalid license key.
To test this, we commented out the license key. We automatically used the demo version that puts a watermark over the generated pdfs, but it told us that it was a wrong license key that messed it up.
I have a WPF application that calls an API and creates an System.Xml.Linq.XDocument using XDocument.Parse(string). I am running into a problem where an XmlException ("Root element is missing") is thrown when I try to do this, but my XML is completely valid. I tried syntax-checking it by calling the API in my browser and checking its syntax, calling the API in my application and Console.WriteLineing the response, and using various XML syntax validators (all of which returned no errors).
A sample XML response from the API is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<response>
<event title="Event 1" id="75823347" icon="www.example.com/images/event1-icon.png" uri="www.example.com/rsvp/event1" mode="none" price="10.00" cover="www.example.com/event1-cover.png" enddate="2016-06-01 14:00:00" startdate="2016-06-01 12:00:00" address="1 Example St, Example City State 12345" location="Example Place" description="This is an event" shortdescription="This is an event" theme="auto" color="#FF000000"/>
</response>
This is my application's code:
public static WebRequest CreateRequest(string baseUrl, string httpMethod, Dictionary<string, string> requestValues) {
var requestItems = requestValues == null ? null : requestValues.Select(pair => string.Format("&{0}={1}", pair.Key, pair.Value));
var requestString = "";
if (requestItems != null)
foreach (var s in requestItems)
requestString += s;
var request = WebRequest.CreateHttp(baseUrl + CredentialRequestString + requestString);
request.Method = httpMethod.ToUpper();
request.ContentType = "application/x-www-form-urlencoded";
request.Credentials = CredentialCache.DefaultCredentials;
return request;
}
public static WebRequest CreateRequest(string apiEndpoint, string endpointParam, int apiVersion, string httpMethod, Dictionary<string, string> requestValues) {
return CreateRequest(string.Format("http://www.example.com/api/v{0}/{1}/{2}", apiVersion, apiEndpoint, endpointParam), httpMethod, requestValues);
}
public static async Task<string> GetResponseFromServer(WebRequest request) {
string s;
using (var response = await request.GetResponseAsync()) {
using (var responseStream = response.GetResponseStream()) {
using (var streamReader = new StreamReader(responseStream)) {
s = streamReader.ReadToEnd();
}
}
}
return s;
}
public static async Task<List<Event>> GetEvents() {
var response = await GetResponseFromServer(CreateRequest("events", "", 1, "GET", null));
Console.WriteLine(response); //validation
var data = XDocument.Parse(response).Root; //XmlException: Root element is mising
return new List<Event>(data.Elements("event").Select(e => Event.FromXml(e.Value)));
}
Why is this happening?
The following code works
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
var data = XDocument.Load(FILENAME);
Event _event = Event.FromXml(data.Descendants("event").FirstOrDefault());
}
}
public class Event
{
public string title { get ; set; }
public string icon {get; set; }
public string uri { get; set; }
public string mode { get;set; }
public decimal price { get; set; }
public string cover { get; set; }
public DateTime enddate { get; set; }
public DateTime startdate { get; set; }
public string address { get; set; }
public string location { get; set; }
public string description { get; set; }
public string shortdescription { get; set; }
public string theme { get; set; }
public uint color { get; set; }
public static Event FromXml(XElement data)
{
Event _event = new Event();
_event.title = (string)data.Attribute("title");
_event.icon = (string)data.Attribute("icon");
_event.uri = (string)data.Attribute("uri");
_event.mode = (string)data.Attribute("mode");
_event.price = (decimal)data.Attribute("price");
_event.cover = (string)data.Attribute("cover");
_event.enddate = (DateTime)data.Attribute("enddate");
_event.startdate = (DateTime)data.Attribute("startdate");
_event.address = (string)data.Attribute("address");
_event.location = (string)data.Attribute("location");
_event.description = (string)data.Attribute("description");
_event.shortdescription = (string)data.Attribute("shortdescription");
_event.theme = (string)data.Attribute("theme");
_event.color = uint.Parse(data.Attribute("color").Value.Substring(1), System.Globalization.NumberStyles.HexNumber) ;
return _event;
}
}
}
I found some new APIs in Windows 10 Mobile device portal that allows to run applications on user phone .
you can launch this like to see the result : http://{PhoneIP}/api/app/packagemanager/packages
and there's another API to launch applications :
api/taskmanager/app
Starts a modern app
HTTP verb: POST
Parameters
appid : PRAID of app to start, hex64 encoded
package : Full name of the app package, hex64 encoded
I have this code to run applications but doesn't work any idea ?
public class PackageInfoToRun
{
public string appid { get; set; }
public string package { get; set; }
public string PackageFamilyName { get; set; }
}
public class PhoneInstalledPackages
{
public Installedpackage[] InstalledPackages { get; set; }
}
public class Installedpackage
{
public string Name { get; set; }
public string PackageFamilyName { get; set; }
public string PackageFullName { get; set; }
public int PackageOrigin { get; set; }
public string PackageRelativeId { get; set; }
public bool IsXAP { get; set; }
}
private static string Encode(string strn)
{
var toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(strn);
string appName64 = System.Convert.ToBase64String(toEncodeAsBytes);
appName64 = appName64.Replace(" ", "20%");
return appName64;
}
public async Task<PhoneInstalledPackages> GetInstalledApps()
{
// /api/app/packagemanager/packages
HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create("http://127.0.0.1/api/app/packagemanager/packages");
string res = "";
webrequest.Method = "GET";
try
{
using (var webresponse = await webrequest.GetResponseAsync())
using (StreamReader loResponseStream = new StreamReader(webresponse.GetResponseStream()))
{
res = loResponseStream.ReadToEnd();
}
var des = JsonConvert.DeserializeObject<PhoneInstalledPackages>(res);
return des;
}
catch (Exception ex)
{
return null;
}
}
public async Task<bool> RunAppAsync(string appid, string packagename)
{
HttpResponseMessage http = new HttpResponseMessage();
string str;
try
{
var package = new PackageInfoToRun()
{
appid = Encode(appid),
package = Encode(packagename)
};
using (HttpClient client = new HttpClient())
{
var serial = JsonConvert.SerializeObject(package);
http = await client.PostAsync("http://127.0.0.1/api/taskmanager/app", new StringContent(serial, Encoding.UTF8, "application/json"));
using (HttpResponseMessage response = http)
{
str = await response.Content.ReadAsStringAsync();
string retur = str;
if (retur.Contains("true"))
{
return true;
}
return false;
}
}
}
catch (Exception ex)
{
return false;
}
}
what's going wrong in my codes ? thanks :)
I used your code with small changes and it works for me.
now RunAppAsync looks like this. Don't forget to specify a PORT.
HttpClient client = new HttpClient();
var serial = JsonConvert.SerializeObject(package);
var result = await client.PostAsync(String.Format("http://127.0.0.1:*PORT*/api/taskmanager/app?appid={0}&package={1}", package.appid, package.package), new StringContent(serial));
Where the package is
var package = new PackageInfoToRun()
{
appid = Encode(app.PackageRelativeId),
package = Encode(app.PackageFullName),
};
And the app variable is an instance of InstalledPackage class.