为何出现这篇这么奇怪的文章,一个Drupal Web网站与C#的连接,原本也没有想过要用C#来连接WEB的。需求是从条码登记开始的,考虑到目前的安卓的扫描枪还是成本较高,使用了几年前的WinCE的扫描枪,旧的扫描条码要将扫描数据上传到网站中,操作步骤又多,对用户的要求也高。所以就考虑了直接安装USB的扫描枪到电脑进行桌面扫描。要求登录后,只扫描一种条码。根据登录的人,来确定条码的状态。
需求提出来了,就开始找方案,开始使用的Rest Server,后面再改Restful方案,想用2.0的,但还有个兼容问题没有解决,只能先用1.0.服务端搞好了,接下来就开始整理桌面端,开始用VS2010,网上的各种方案都看遍了没有几个是说C# 与Drupal 7 的,与Drupal 7的Restful 方案的文档,基本没有找到。后面找C#微软REST的相关资料,发现Drupal.server 的项目,一看是2015版的,马上换了15版本。又在官方找到下面的参考,在http://stackoverflow.com/上又找到一些参考,不断的摸索,有了下面的一段程序,
希望给有需要的Drupaler一点帮助。
首先设定我们的Drupal7 Restful服务正常开启,通过/api/login进行认证。还没有了解Restful的可以参考下我的关于Restful之一二三四五的连接。
下面主要根据http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client参考与多方面的查找资料,找到下面的解决方案:
今天一整天就为这个小段晕死了,上面的参考有好些都没有写细,Using都没有完全写在教程中,造成我多次没搞明白引用了什么,本文的Using也很清楚。
using System;
using System.Text;
using System.Windows.Forms;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Handlers;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;
namespace samplescan
{
public partial class Form1 : Form
{
public class login_user
{
public string ID { get; set; }
public string label { get; set; }
public string self { get; set; }
public string mail { get; set; }
public string X_CSRF_Token { get; set; }
public string count { get; set; }
//public string SELF { get; set; }
}
public class samplescan
{
}
private const string base_url = "http://drupal-7-50.dd:8083/api/";
private HttpResponseMessage myclient = new HttpResponseMessage();
private login_user current_user;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
}
private async void button2_Click(object sender, EventArgs e)
{
bool login_bool = true;
string login_account = "";
if (textBox3.Text.Trim() == "")
{
MessageBox.Show("请输入登录用户", "登录提示");
textBox3.Focus();
login_bool = false;
return;
}
if (textBox4.Text.Trim() == "")
{
MessageBox.Show("请输入登录密码", "登录提示");
textBox4.Focus();
login_bool = false;
return;
}
if (login_bool == false)
{
MessageBox.Show("登录用户和密码不可为空", "登录提示");
return;
}
else
{
login_account = textBox3.Text.Trim() + ":" + textBox4.Text.Trim();
try
{
myclient = await LoginAsync(login_account);
var formatters = new List<MediaTypeFormatter>() {
new JsonMediaTypeFormatter(),
new XmlMediaTypeFormatter()
};
if (myclient != null)
{
current_user = await myclient.Content.ReadAsAsync<login_user>();
MessageBox.Show("登录成功", "登录提示");
button2.Visible = false;
button3.Visible = true;
textBox1.Enabled = true;
dataGridView1.Visible = true;
tabControl1.SelectedIndex = 1;
}
else
{
MessageBox.Show("登录失败", "登录提示");
}
}
catch (Exception ex)
{
throw ex;
}
}
}
private void button3_Click(object sender, EventArgs e)
{
myclient.Dispose();
Application.Exit();
}
private void Form1_Load(object sender, EventArgs e)
{
TopMost = true;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (this.textBox1.Text.Length == 12)
{
SendKeys.Send("{Enter}");
}
}
private void tabPage1_Click(object sender, EventArgs e)
{
}
static async Task<HttpResponseMessage> LoginAsync(string login_account)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(base_url);
byte[] cred = UTF8Encoding.UTF8.GetBytes(login_account);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(cred));
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
//Http Get login
var response = await client.GetAsync("login");
try
{
if (response.IsSuccessStatusCode)
{
return response;
}
else
{
return null;
}
}
catch (HttpRequestException ex) { throw ex; }
finally { client.Dispose(); }
}
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
try
{
}
catch (Exception ex) { throw ex; }
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (myclient != null) {
myclient.Dispose();
Application.Exit();
}
}
}
}
通过以上操作可以进行登录了,目前已取到token所在的json字符串,现在卡在如何把字符串整成数组这块了。
An exception of type 'Newtonsoft.Json.JsonReaderException' occurred in samplescan.exe but was not handled in user code
这个错误。。还在解决中。
Additional information: Unexpected character encountered while parsing value: {. Path 'self', line 1, position 202.
真的是没有匹配好Json的排序。设置好了登录信息的自定义类后,成功了。
using System;
using System.Text;
using System.Windows.Forms;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Handlers;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;
namespace samplescan
{
public partial class Form1 : Form
{
//private const string base_url = "http://www.tsghy.com.cn/api/";
private const string base_url = "http://drupal-7-50.dd:8083/api/";
private HttpResponseMessage myclient = new HttpResponseMessage();
public class login_data {
public string id { get; set; }
public string label { get; set; }
public string SELF { get; set; }
public string mail { get; set; }
public string X_CSRF_Token { get; set; }
public string name { get; set; }
}
public class login_SELF {
public string title { get; set; }
public string href { get; set; }
}
public class login_user {
public login_data data { get; set; }
public Int64 count { get; set; }
public login_SELF SELF { get; set; }
}
private login_user current_user ;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
}
private async void button2_Click(object sender, EventArgs e)
{
bool login_bool = true;
string login_account = "";
if (textBox3.Text.Trim() == "")
{
MessageBox.Show("请输入登录用户", "登录提示");
textBox3.Focus();
login_bool = false;
return;
}
if (textBox4.Text.Trim() == "")
{
MessageBox.Show("请输入登录密码", "登录提示");
textBox4.Focus();
login_bool = false;
return;
}
if (login_bool == false)
{
MessageBox.Show("登录用户和密码不可为空", "登录提示");
return;
}
else
{
login_account = textBox3.Text.Trim() + ":" + textBox4.Text.Trim();
try
{
//Task<HttpClient> myclient=Task.Run<HttpClient>(LoginAsync(login_account));
myclient = await LoginAsync(login_account);
//var jsonTypeFormatter = new JsonMediaTypeFormatter();
if (myclient != null)
{
current_user = await myclient.Content.ReadAsAsync<login_user>();
MessageBox.Show(current_user.data.id);
MessageBox.Show("登录成功", "登录提示");
button2.Visible = false;
button3.Visible = true;
textBox1.Enabled = true;
dataGridView1.Visible = true;
tabControl1.SelectedIndex = 1;
}
else
{
MessageBox.Show("登录失败", "登录提示");
}
}
catch (Exception ex)
{
throw ex;
}
}
}
private void button3_Click(object sender, EventArgs e)
{
myclient.Dispose();
Application.Exit();
}
private void Form1_Load(object sender, EventArgs e)
{
TopMost = true;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (this.textBox1.Text.Length == 12)
{
SendKeys.Send("{Enter}");
}
}
private void tabPage1_Click(object sender, EventArgs e)
{
}
static async Task<HttpResponseMessage> LoginAsync(string login_account)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(base_url);
byte[] cred = UTF8Encoding.UTF8.GetBytes(login_account);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(cred));
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
//Http Get login
var response = await client.GetAsync("login");
try
{
if (response.IsSuccessStatusCode)
{
return response;
}
else
{
return null;
}
}
catch (HttpRequestException ex) { throw ex; }
finally { client.Dispose(); }
}
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
try
{
}
catch (Exception ex) { throw ex; }
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (myclient != null) {
myclient.Dispose();
Application.Exit();
}
}
}
}
最后还有一个问题,Drupal返回的Json中名称中有-号,在C#中认为是操作符,不能直接使用,要用_替换下,所以有下面小段要修改下:
加上system.io;
TextReader tr = new StreamReader(await myclient.Content.ReadAsStreamAsync());
var json = tr.ReadToEnd();
var thing = JsonConvert.DeserializeObject(json);
string thing_replace = thing.ToString().Replace("-", "_");
current_user = JsonConvert.DeserializeObject<login_user>(thing_replace);
方法不可能是一种,还有可能很多,希望抛砖引玉,让drupal的高手能再优化。
参考的文章有:
http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client
http://drupal.stackexchange.com/questions/79497/new-user-registration-sequence-for-services-3-4
https://blogs.msdn.microsoft.com/webdev/2013/07/19/writing-web-api-client-code-for-multiple-platforms-using-portable-libraries/
http://stackoverflow.com/questions/34834488/an-unhandled-exception-of-type-newtonsoft-json-jsonreaderexception-occurred-in
http://blog.csdn.net/coolszy/article/details/8606803
http://www.cnblogs.com/chenwolong/p/JSON.html