C# 从模型传递数据

C# 从模型传递数据,c#,rest,model-view-controller,salesforce,C#,Rest,Model View Controller,Salesforce,我目前正在使用Salesforce API填充数据 在我的帐户控制器中,我有一个使用Salesforce用户名/密码流来授权API使用的方法,我附加了这个方法,以便它在登录时执行此操作,这个过程很好,它可以工作,我已经对它进行了测试 但是当我的问题出现时,我需要访问它在登录时生成的AccessToken值和ServiceUrl值,以便在另一个控制器中使用我的方法,例如“GetEvents” 目前我使用的是模型,根本没有数据上下文,因为我不需要它。但是,如果我要在另一个控制器中使用AccessTo

我目前正在使用Salesforce API填充数据

在我的帐户控制器中,我有一个使用Salesforce用户名/密码流来授权API使用的方法,我附加了这个方法,以便它在登录时执行此操作,这个过程很好,它可以工作,我已经对它进行了测试

但是当我的问题出现时,我需要访问它在登录时生成的AccessToken值和ServiceUrl值,以便在另一个控制器中使用我的方法,例如“GetEvents”

目前我使用的是模型,根本没有数据上下文,因为我不需要它。但是,如果我要在另一个控制器中使用AccessToken属性实例化此模型,则该值将不会从生成此令牌的控制器方法传递

请记住,这些方法工作得很好,但我需要获得查看这些事件的授权,如果它没有登录方法中的AccessToken和ServiceUrl,我就无法查看任何事件

我该怎么办

HomeController中的方法

        public async void GetAllEvents()
        {
            TokenModel tm = new TokenModel();

            HttpClient queryClient = new HttpClient();

            string restQuery = tm.ServiceUrl + "/services/data/v25.0/query?q=SELECT+Subject+from+Event";
            Console.WriteLine(restQuery);

            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, restQuery);
            Console.WriteLine(request);

            // Adding the token to the header 
            request.Headers.Add("Authorization", "Bearer " + tm.AccessToken);
            // Return JSON to the caller
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            //Call Endpoint Async
            HttpResponseMessage response = await queryClient.SendAsync(request);

            string result = await response.Content.ReadAsStringAsync();
            Console.WriteLine(result);
        }
        [HttpPost]
        [AllowAnonymous]
        public IActionResult Login(AuthRequestModel authRequest)
        {
            if (!ModelState.IsValid)
            {
                return View(authRequest);
            }

            if(authRequest == null)
            {
                return BadRequest("Authorization is missing");
            }

            var isAuth = Authentication.ActiveDirectoryValidation(authRequest.Username, authRequest.Password);
            if(isAuth == true)
            {
                AuthR().Wait();
                return RedirectToAction("Index", "Home");
            }

            return View();
        }

        // Salesforce Username / Password Validation
        public async Task<string> AuthR()
        {
            TokenModel tm = new TokenModel();
            var handler = new HttpClientHandler()
            {
                SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
            };

            HttpClient authClient = new HttpClient(handler);

            string clientId = _config.GetSection("Keys").GetSection("client_id").Value;
            string clientSecret = _config.GetSection("Keys").GetSection("client_secret").Value;
            string username = _config.GetSection("Keys").GetSection("username").Value;
            string password = _config.GetSection("Keys").GetSection("password").Value;

            HttpContent content = new FormUrlEncodedContent(new Dictionary<string, string>
            {
                {"grant_type","password"},
                {"client_id",clientId},
                {"client_secret",clientSecret},
                {"username",username},
                {"password",password}
            }
          );

            HttpResponseMessage message = await
            authClient.PostAsync("https://test.salesforce.com/services/oauth2/token", content);

            string responseString = await message.Content.ReadAsStringAsync();
            var model = JsonConvert.DeserializeObject<Dictionary<string, string>>(responseString);

            tm.AccessToken = model["access_token"];
            tm.ServiceUrl = model["instance_url"];

            return tm.AccessToken;
        }
AccountController中的方法

        public async void GetAllEvents()
        {
            TokenModel tm = new TokenModel();

            HttpClient queryClient = new HttpClient();

            string restQuery = tm.ServiceUrl + "/services/data/v25.0/query?q=SELECT+Subject+from+Event";
            Console.WriteLine(restQuery);

            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, restQuery);
            Console.WriteLine(request);

            // Adding the token to the header 
            request.Headers.Add("Authorization", "Bearer " + tm.AccessToken);
            // Return JSON to the caller
            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            //Call Endpoint Async
            HttpResponseMessage response = await queryClient.SendAsync(request);

            string result = await response.Content.ReadAsStringAsync();
            Console.WriteLine(result);
        }
        [HttpPost]
        [AllowAnonymous]
        public IActionResult Login(AuthRequestModel authRequest)
        {
            if (!ModelState.IsValid)
            {
                return View(authRequest);
            }

            if(authRequest == null)
            {
                return BadRequest("Authorization is missing");
            }

            var isAuth = Authentication.ActiveDirectoryValidation(authRequest.Username, authRequest.Password);
            if(isAuth == true)
            {
                AuthR().Wait();
                return RedirectToAction("Index", "Home");
            }

            return View();
        }

        // Salesforce Username / Password Validation
        public async Task<string> AuthR()
        {
            TokenModel tm = new TokenModel();
            var handler = new HttpClientHandler()
            {
                SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
            };

            HttpClient authClient = new HttpClient(handler);

            string clientId = _config.GetSection("Keys").GetSection("client_id").Value;
            string clientSecret = _config.GetSection("Keys").GetSection("client_secret").Value;
            string username = _config.GetSection("Keys").GetSection("username").Value;
            string password = _config.GetSection("Keys").GetSection("password").Value;

            HttpContent content = new FormUrlEncodedContent(new Dictionary<string, string>
            {
                {"grant_type","password"},
                {"client_id",clientId},
                {"client_secret",clientSecret},
                {"username",username},
                {"password",password}
            }
          );

            HttpResponseMessage message = await
            authClient.PostAsync("https://test.salesforce.com/services/oauth2/token", content);

            string responseString = await message.Content.ReadAsStringAsync();
            var model = JsonConvert.DeserializeObject<Dictionary<string, string>>(responseString);

            tm.AccessToken = model["access_token"];
            tm.ServiceUrl = model["instance_url"];

            return tm.AccessToken;
        }
[HttpPost]
[异名]
公共IActionResult登录(AuthRequestModel authRequest)
{
如果(!ModelState.IsValid)
{
返回视图(authRequest);
}
if(authRequest==null)
{
返回请求(“缺少授权”);
}
var isAuth=Authentication.ActiveDirectoryValidation(authRequest.Username,authRequest.Password);
if(isAuth==true)
{
AuthR().Wait();
返回重定向到操作(“索引”、“主页”);
}
返回视图();
}
//Salesforce用户名/密码验证
公共异步任务AuthR()
{
TokenModel tm=新的TokenModel();
var handler=new-HttpClientHandler()
{
SslProtocols=SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
};
HttpClient authClient=新的HttpClient(处理程序);
字符串clientId=\u config.GetSection(“键”).GetSection(“客户端id”).Value;
字符串clientSecret=_config.GetSection(“key”).GetSection(“client_secret”).Value;
字符串用户名=_config.GetSection(“key”).GetSection(“username”).Value;
字符串密码=_config.GetSection(“key”).GetSection(“password”).Value;
HttpContent=新的FormUrlEncodedContent(新字典
{
{“授权类型”,“密码”},
{“client_id”,clientId},
{“客户机密”,clientSecret},
{“用户名”,用户名},
{“密码”,密码}
}
);
HttpResponseMessage消息=等待
authClient.PostAsync(“https://test.salesforce.com/services/oauth2/token“,内容);
string responseString=wait message.Content.ReadAsStringAsync();
var model=JsonConvert.DeserializeObject(responseString);
tm.AccessToken=模型[“访问令牌”];
tm.ServiceUrl=model[“实例url”];
返回tm.AccessToken;
}
我不是一个C#人,但可能你应该有一个单独的类来进行新的登录调用或重用现有的会话id。可以是静态方法,也可以是单例模式(无论C#中的哪个词合适);如果从另一个模型(线程?)调用静态行为正常。在一些全局变量中共享会话id可能也可以正常工作,但有点难闻

也许你必须将会话id存储在某个地方(如果你没有可用的内存缓存,那么可能是文件?数据库?),加密与否

登录到SF的经过战斗测试的模式看起来有点像这样

do we have cached session id?
    no -> call login()
        -> it worked? great, cache new session id somewhere
        -> didn't work (account deactivated, password expired, network problems) - you have bigger problems your program probably can't recover from nicely, notify user? There's way to reset password via API but it's bit "pro"
    yes -> try to use it
        -> worked? great
        -> error? check the details / HTTP error code and if it's for example session id expired - call new login & handle it like above
根据身份验证方法,当会话id即将过期时,您将获得信息(例如,从现在起2小时,但每次使用API都会重置计数器)。别指望太多了。SF管理员可以随时终止您的会话(例如防止黑客访问)。或者,对于相同的凭证,可以打开的会话有一定的限制,过去类似于第5个login()调用使最早的会话id无效