以下是我的代码。
我正在构建 ac# 窗口应用程序以从 url 获取一些信息,而无需登录但自动登录。
它是一个窗口应用程序表单,当用户单击接受按钮时将输出课程设置。此代码基于 valence-client-side 示例代码。我希望这个应用程序使用应用程序 ID/密钥对和用户 ID/密钥对登录并获取课程设置并输出它们。但是,当我运行这个程序时,它只会停止var ctx = httpListener.GetContext(); 在这条线上。我不希望它打开浏览器,但希望在 c# 中使用应用程序和用户 ID/密钥对自动登录,并从 url 获取 json 响应。所以用户不必登录。
namespace CourseOfferingWindow
{
class CourseOfferingResponse
{
public string Identifier { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public bool IsActive { get; set; }
public string Path { get; set; }
public object StartDate { get; set; }
public object EndDate { get; set; }
public string CourseTemplate { get; set; }
public string Semester { get; set; }
public string Department { get; set; }
}
public partial class CourseOfferingWindowForm : Form
{
public CourseOfferingWindowForm()
{
InitializeComponent();
}
private static ID2LUserContext InterceptUserTokens(HostSpec host, ID2LAppContext appContext)
{
// Start HTTP server and listen for the redirect after a successful auth
var httpListener = new HttpListener();
httpListener.Prefixes.Add("http://localhost:31337/result/");
httpListener.Start();
// This call blocks until we get a response
var ctx = httpListener.GetContext();
// The LMS returns the user tokens via query parameters to the value provided originally in x_target
// TODO: deal with "failed to login" case
var userContext = appContext.CreateUserContext(ctx.Request.Url, host);
// Send some JavaScript to close the browser popup
// This is not 100% effective: for example, Firefox will ignore this.
const string RESPONSE = "<!doctype html><meta charset=\"utf-8\"><script>window.close();</script><h1>You may now close your window</h1><p>You may or may not see this message, depending on your browser</p>";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(RESPONSE);
ctx.Response.ContentType = "text/html";
ctx.Response.ContentLength64 = buffer.Length;
ctx.Response.OutputStream.Write(buffer, 0, buffer.Length);
ctx.Response.OutputStream.Close();
httpListener.Stop();
return userContext;
}
private static void DoApiStuff(string host, ID2LUserContext userContext)
{
const string COURSEOFFERING_ROUTE = "/d2l/api/lp/1.0/courses/644849";
var client = new RestClient(host);
var valenceAuthenticator = new D2L.Extensibility.AuthSdk.Restsharp.ValenceAuthenticator(userContext);
var request = new RestRequest(COURSEOFFERING_ROUTE, Method.GET);
valenceAuthenticator.Authenticate(client, request);
var response = client.Execute<CourseOfferingResponse>(request);
Console.WriteLine("Hello, " + {course offerings information} );
}
private void ButtonAccept_Click(object sender, EventArgs e)
{
// This is the LMS we will interact with
var host = new HostSpec("https", "www.foltest.ca", 443);
// The appId/appKey come from our app.config - it is good to seperate access keys from the code that uses them.
// Ideally you wouldn't have production keys committed to source control.
string appId = ConfigurationManager.AppSettings["appId"];
string appKey = ConfigurationManager.AppSettings["appKey"];
// This is the port we will temporarily host a server on to intercept the user tokens after a successful login
int port = int.Parse(ConfigurationManager.AppSettings["serverPort"]);
// Create url for the user to login. If they have already done so they will not actually have to type their password (maybe).
var appContextFactory = new D2LAppContextFactory();
var appContext = appContextFactory.Create(appId, appKey);
var authUrl = appContext.CreateUrlForAuthentication(host, new Uri("http://localhost:" + port + "/result/"));
//OpenBrowser(authUrl);
// This call will block until we have a result
// TODO: you'll want better control flow and error handling here
var userContext = InterceptUserTokens(host, appContext);
// Now we can call Valence
DoApiStuff(host.Scheme + "://" + host.Host + ":" + host.Port, userContext);
// Pause the terminal
Console.ReadKey();
}
}
}
任何形式的帮助将不胜感激。谢谢,菲利普