How secure this PHP encryption/decryption will be? - security

I am working in a project where users will need to encrypt/decrypt data. The encrypted data will be saved in a MySQL Database. The users do login from a a login page login.php and the function Login() is called. Data is encrypted and Peppers are added at the end. Why? In case someone hacks the MySQL Database, the data is garbage for them because they also will need to have the Peppers to encrypt/decrypt data. The function ValidateLogin is not posted here but, the function is going to receive clear-text email and the encrypted password to validate if records exist in MySQL login table. Please answer me these questions:
What is the best cipher to use? (I have no clue about this but, I am
using AES-256-CBC
Do you think my script is good/secure enough to protect data?
File: peppers.php
<?php
define('PEPPER_PASSPHRASE', 'JkKli7YHUim6KH7tgyU6h56rykguhnBRvh23456%$%$#4c35$^$^Nm5GrBYB');
define('PEPPER_KEY', '6I7j5ih6tYHgbG4#$g%&h^&35$^g%7$VC$s23X#$%c^v$c35V^&b%&N6M8j^%4C54^#C5');
define('PEPPER_IV', '$^g%7&%b*45#$#4TF34TC3FG67H6755741532557B6$^v%$7$^^#$#%f&&B5B7V^*$6787');
?>
File: functions.php
function Login(){
$email = htmlentities($_POST["email"], ENT_QUOTES, "UTF-8");
$password = htmlentities($_POST["password"], ENT_QUOTES, "UTF-8");
if($email == NULL){ exit("Email can't be empty"); }
if($password == NULL){ exit("Password can't be empty"); }
#session_start();
$_SESSION["passphrase"] = hash("SHA256", $password.PEPPER_PASSPHRASE);
$password_encrypted = EncryptData($password);
$password = NULL;
ValidateLogin($email, $password_encrypted);
}
function EncryptData($data){
#session_start();
#$passphrase = $_SESSION["passphrase"];
if($data == NULL){ exit("Missing data to encrypt"); }
if($passphrase == NULL){ exit("Passphrase is not set"); }
$key = hash("SHA256", $passphrase.PEPPER_KEY);
$iv = substr(hash("SHA256", $passphrase.PEPPER_IV), 0, 16);
$output = openssl_encrypt($data, "AES-256-CBC", $key, 0, $iv);
return $output;
}
function DecryptData($data){
#session_start();
#$passphrase = $_SESSION["passphrase"];
if($data == NULL){ exit("Missing data to encrypt"); }
if($passphrase == NULL){ exit("Passphrase is not set"); }
$key = hash("SHA256", $passphrase.PEPPER_KEY);
$iv = substr(hash("SHA256", $passphrase.PEPPER_IV), 0, 16);
$output = openssl_decrypt($data, "AES-256-CBC", $key, 0, $iv);
return $output;
}

Related

Azure speech to text with numbers

A use case for my app is to convert speech (single word utterances) to text. I need to use Azure speech to text for this. Sometimes the speech needs to be converted into an integer - I need to submit the response as a quantity for example.
My question is is there anyway, via the REST API, to tell the speech to text service I want a numeric result? Currently it is returning things like 'one' instead of '1' and 'free' instead of '3'. I don't think there is a way to do this from the documentation but I wanted to see if anyone else has solved this problem before I think of a way around it.
This is the code I am using in my proof of concept project:
public static async Task SpeechToTextAsync(MemoryStream data, ISpeechResultCallback callBack)
{
string accessToken = await Authentication.GetAccessToken();
IToast toastWrapper = DependencyService.Get<IToast>();
if (accessToken != null)
{
toastWrapper.Show("Acquired token");
callBack.SpeechReturned("Acquired token");
using (var client = new HttpClient())
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://westus.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1?language=en-GB&format=detailed");
request.SendChunked = true;
request.Accept = #"application/json;text/xml";
request.Method = "POST";
request.ProtocolVersion = HttpVersion.Version11;
request.Host = "westus.stt.speech.microsoft.com";
request.ContentType = #"audio/wav; codecs=audio/pcm; samplerate=16000";
// request.Headers["Ocp-Apim-Subscription-Key"] = Program.SubscriptionKey;
request.Headers.Add("Authorization", "Bearer " + accessToken);
request.AllowWriteStreamBuffering = false;
data.Position = 0;
byte[] buffer = null;
int bytesRead = 0;
using (Stream requestStream = request.GetRequestStream())
{
buffer = new Byte[checked((uint)Math.Min(1024, (int)data.Length))];
while ((bytesRead = data.Read(buffer, 0, buffer.Length)) != 0)
{
requestStream.Write(buffer, 0, bytesRead);
}
// Flush
requestStream.Flush();
}
try
{
string responseData = null;
using (WebResponse response = request.GetResponse())
{
var encoding = Encoding.GetEncoding(((HttpWebResponse)response).CharacterSet);
using (var responseStream = response.GetResponseStream())
{
using (var reader = new StreamReader(responseStream, encoding))
{
responseData = reader.ReadToEnd();
AzureSTTResults deserializedProduct = JsonConvert.DeserializeObject<AzureSTTResults>(responseData);
if(deserializedProduct == null || deserializedProduct.NBest == null || deserializedProduct.NBest.Length == 0)
{
toastWrapper.Show("No results");
callBack.SpeechReturned("No results");
}
else
{
toastWrapper.Show(deserializedProduct.NBest[0].ITN);
callBack.SpeechReturned(deserializedProduct.NBest[0].ITN);
}
}
}
}
}
catch (Exception ex)
{
toastWrapper.Show(ex.Message);
callBack.SpeechReturned(ex.Message);
}
}
}
else
{
toastWrapper.Show("No token required");
callBack.SpeechReturned("No token required");
}
}
And here is an example of the result that I would like to be '1':
{
"RecognitionStatus": "Success",
"Offset": 0,
"Duration": 22200000,
"NBest": [
{
"Confidence": 0.43084684014320374,
"Lexical": "one",
"ITN": "One",
"MaskedITN": "One",
"Display": "One."
}
]
}
I suggest to use this nuget from Microsoft. It works like a charm, here an example.
NumberRecognizer.RecognizeNumber("I have two apples", Culture.English)
According to the offical document Speech-to-text REST API, there is no option can help converting the numberic words to numbers.
Considering for the numberic words in English have the pattern in syntax, you can use a simple algorithm to implement the feature for converting words to numbers. As references, you can follow these below to write your own one in C# by yourself.
Converting words to numbers in c++
Translate (Convert) Words to Numbers RRS feed in SQL Server
Words in Numbers
Hope it helps.

Stripe ach payment getway without plaid get account number and routing number of bank

i am trying to use ACH stripe getaway without palid third party to get manually account number ,routing number ,account holder name nd account type stripe.js/v3 create bank token i use this token create customer and then create charge all thing is done but when we test using stripe testng account num and reuting number this give me fatal error "this account cannot create payment"
this is my onclick button function that create abnk token
function test1(){
var one_coach = $('input.checkbox-coaches').is(':checked');
if(one_coach == false){
alert('Please Choose at least one coach');
return false;
}
var one_athlete = $('input.checkbox-athletes').is(':checked');
if(one_athlete == false){
alert('Please Choose at least one athlete');
return false;
}
//create single-use token to charge the use
var stripe = Stripe('pk_test_UM0qUCRVFnrem3uAIGtWcPiJ');
//create single-use token to charge the use
stripe.createToken('bank_account', {
country: 'US',
currency: 'usd',
routing_number: $('#routing_number').val(),
account_number: $('#account_number').val(),
account_holder_name: $('#account_holder_name').val(),
account_holder_type: $('#account_holder_type').val(),
}).then(function(result) {
//console.log(result);
if (result.error) {
//enable the submit button
$('#payBtn').removeAttr("disabled");
//display the errors on the form
// $('#payment-errors').attr('hidden', 'false');
$('#payment-errors').addClass('alert alert-danger');
$("#payment-errors").html(result.error.message);
} else {
var form$ = $("#order_form");
//get token id
var token_ach = result.token.id;
var bank_account_id=result.token.bank_account.id;
//alert(token_ach);
//insert the token into the form
form$.append("<input type='hidden' id='bank_account' name='bank_account' value='" + bank_account_id + "' />");
form$.append("<input type='hidden' id='stripeToken' name='stripeToken' value='" + token_ach + "' />");
//submit form to the server
// form$.get(0).submit();
function ach(){
var charges = $( "#service_charges" ).text();
var formdata=$('#order_form').serialize()+ '&charges=' + charges;
$('#ach_button').attr('disabled','disabled').attr('value','Ordering...');
$.ajax({
type : 'POST',
url : 'register/ach',
data : formdata,
beforeSend: function() {
$("#loader").show();
},
success:
function(data){
$('#results').removeClass('hide');
var result = JSON.parse(data);
if(result.error == 100)
{
$("#loader").hide();
$('#alert_msg').addClass('alert-error');
$('#results h4').text('On snap!');
$('#results p').text(result.msg);
$('#place_order').removeClass('disabled').attr('value','Place Order').removeAttr('disabled');
}
else
{
$("#loader").hide();
$('#alert_msg').removeClass('alert-error').addClass('alert-success');
$('#results h4').text('Congratulations!');
$('#results p').html(result.msg + '<br/>An email confirmation has been sent to you. You can visit the My Account area to view your invoice.');
return false;
}
return false;
}
});
}
// $('#stripeToken').val(token);
}
});
// var token = $('#stripeToken').val();
// alert(token); return;
// //submit from callback
// process_order(token);
}
php code that get all data
public function ach()
{
$post = array_2_obj($this->input->post());
if(!empty($post->stripeToken))
{
$contact_id = $this->club->infusion_contact_id;
$post->event = $this->events_model->get('events',array('id' => $post->event_id));
$attending = $this->get_attending_details($post->event_id,$this->input->post('athletes'));
//echo "<pre>";print_r($attending);
$teams = $this->get_team_comps($post->event_id,$attending);
// echo "<pre>";print_r($teams);
$this->session->unset_userdata("register_{$post->event_id}");
/**
* Check if Order has already been created by Session register_{event_id} Create Blank Order inside Infusionsoft
*/
if(!isset($this->session->userdata["register_{$post->event_id}"])):
$invoice_id = $this->infusion->create_order($contact_id,$post,$attending,$teams);
$this->session->set_userdata("register_{$post->event_id}",$invoice_id);
else :
$invoice_id = $this->session->userdata["register_{$post->event_id}"];
endif;
/**
* Charge Invoice
*/
// $merchant_id = $this->db_model->get_setting_value('merchant_id');
/**
* Unset the Invoice Id
*/
//$this->session->unset_userdata("register_{$post->event_id}");
//print_r($post); exit;
// echo "<pre>";print_r($_POST);
//get token, card and user info from the form
$bank_a_token = $post->stripeToken;
$account_holder_name = $post->account_holder_name;
// $email = $_POST['email'];
$routing_number = $post->routing_number;
$account_number =$post->account_number;
// $bank_account_id=$post->bank_account;
//include Stripe PHP library
require_once APPPATH."third_party/stripe/init.php";
//set api key
$stripe = array(
"secret_key" => "sk_test_HfRFUzMnvuq1rY1CfBZZUgKv",
"publishable_key" => "pk_test_UM0qUCRVFnrem3uAIGtWcPiJ"
);
\Stripe\Stripe::setApiKey($stripe['secret_key']);
$create_customer=\Stripe\Customer::create(array(
"source" => $bank_a_token,
"description" => $account_holder_name
));
//print_r($create_customer); exit;
$customer_id=$create_customer->id;
$source=$create_customer->default_source;
//get the existing bank account
$customer = \Stripe\Customer::retrieve($customer_id);
$bank_account = $customer->sources->retrieve($source);
// verify the account
$bank_account->verify(array('amounts' => array(32, 45)));
//print_r($bank_account); exit;
$label="";
$price=0;
$teamprice=0;
$teamlable="";
//item information
foreach ($attending as $product) {
$label.=$product->label.",";
$price=($product->total)+$price;
}
if (!empty($teams)) {
foreach ($teams as $tprice) {
$teamlable.=$tprice->label.",";
$teamprice=$tprice->team_price;
}
}
$charges=$post->charges;
$new_price=$price+$teamprice+$charges;
$itemName = $label;
$itemNumber = $post->event->product_id;
$itemPrice = $new_price*100;
$currency = "usd";
$orderID = $post->event->action_set_id;
//print_r($customer);
try {
$charge = \Stripe\Charge::create(array(
"amount" => $itemPrice,
"currency" => $currency,
"customer" => $customer_id // Previously stored, then retrieved
));
} catch(\Stripe\Error\Card $e) {
// Since it's a decline, \Stripe\Error\Card will be caught
$body = $e->getJsonBody();
$err = $body['error'];
print('Status is:' . $e->getHttpStatus() . "\n");
print('Type is:' . $err['type'] . "\n");
print('Code is:' . $err['code'] . "\n");
// param is '' in this case
print('Param is:' . $err['param'] . "\n");
print('Message is:' . $err['message'] . "\n");
} catch (\Stripe\Error\RateLimit $e) {
// Too many requests made to the API too quickly
} catch (\Stripe\Error\InvalidRequest $e) {
$msg = array('error' => 100,'msg' => "this account cannot create payment ");
echo json_encode($msg);
exit;
// Invalid parameters were supplied to Stripe's API
} catch (\Stripe\Error\Authentication $e) {
// Authentication with Stripe's API failed
// (maybe you changed API keys recently)
} catch (\Stripe\Error\ApiConnection $e) {
// Network communication with Stripe failed
} catch (\Stripe\Error\Base $e) {
// Display a very generic error to the user, and maybe send
// yourself an email
} catch (Exception $e) {
$msg = array('error' => 0,'msg' => "this account cannot create payment ");
echo json_encode($msg);
exit;
// Something else happened, completely unrelated to Stripe
}
//retrieve charge details
$chargeJson = $charge->jsonSerialize();
//check whether the charge is successful
if($chargeJson['amount_refunded'] == 0 && $chargeJson['paid'] == 1 && $chargeJson['captured'] == 1)
{
//order details
$amount = $chargeJson['amount'];
$balance_transaction = $chargeJson['balance_transaction'];
$currency = $chargeJson['currency'];
$status = $chargeJson['status'];
$date = date("Y-m-d H:i:s");
//insert tansaction data into the database
$data = new stdClass();
$data->attending_details = $attending;
$data->post = $post;
$data->teams = $teams;
$data->club = new stdClass();
$data->club = $this->club;
$data->bank = new stdClass();
$data->bank->last4 = substr($post->account_number,-4);
$data->bank->account_holder_type = $post->account_holder_type;
$data->bank->account_number = $post->account_number;
$data->bank->routing_number = $post->routing_number;
// $data->card->stripeToken=$post->stripeToken;
unset($data->post->account_number);
unset($data->post->routing_number);
/**
* Add Coaches and Athlete Data so it does not get deleted
*/
$data->coaches = array();
foreach($data->post->coaches as $coach_id):
if($coach_id > 0):
$data->coaches[] = $this->coaches_model->get(array('id' => $coach_id));
endif;
endforeach;
$data->athletes = array();
foreach($data->post->athletes as $athlete_id):
if($athlete_id > 0):
$data->athletes[] = $this->athletes_model->get(array('id' => $athlete_id));
endif;
endforeach;
//Insert Data into Database
$order_data = $this->db_model->add_order($this->club->id,$invoice_id,$data->post->event_id,$data);
$pdf_base64 = execute_curl(base_url() . 'invoice/base/' . $order_data->key,array(),TRUE);
// if(strlen($pdf_base64) > 10 ):
// $file_name = $data->post->event->name . ' - ' . $data->club->club . ' Invoice.pdf';
// $this->infusion->uploadFile($file_name,$pdf_base64,$contact_id);
// endif;
// //Update Invoice Key and then send email
// $this->infusion->updateCon($contact_id,array('_InvoiceKey' => $order_data->key));
// $this->infusion->sendTemplate(array($contact_id),$this->db_model->get_setting_value('invoice_email_template'));
// $this->infusion->sendTemplate(array($contact_id),$this->db_model->get_setting_value('admin_notification_email_template'));
// $global_action_set = $this->db_model->get_setting_value('all_events_action_set_id');
// if(isset($global_action_set) && $global_action_set > 0):
// $this->infusion->runAS($contact_id,$global_action_set);
// endif;
}
// $msg = array('error' => 0,'msg' => "You have successfully registered your club for " . $data->post->event->name. ' Event');
$msg = array('error' => 0,'msg' => "You have successfully registered your club for " . "$chargeforach->". ' Event');
echo json_encode($msg);
exit;
}
else
{
$msg = array('error' => 100,'msg' => "Invalid TOken");
echo json_encode($msg);
exit;
}
}
Are you based in US?
Currently according to the documents. It only supports ACH charges in the US
https://stripe.com/docs/ach

Manually hashing password the same as ASP.NET Identity v2.2.1

I have an ASP.NET Web Api that makes use of ASP.NET Identity v2.2.1 to manage users. I am able to add/edit users without issue. However, I have a second project that cannot make use of the API but needs to be able to change a Users password directly via the database.
I am trying to figure out how to hash the password entered by the user without going through the API. I need to make sure that I am using the same hashing algorithm that ASP.NET Identity is using. I came across some code in this SO article but I am not sure if it is the same hashing algorithm used by v2.2.1.
using using System.Security.Cryptography;
public static string HashPassword(string password)
{
private const int PBKDF2IterCount = 1000; // default for Rfc2898DeriveBytes
private const int PBKDF2SubkeyLength = 256 / 8; // 256 bits
private const int SaltSize = 128 / 8; // 128 bits
if (password == null)
{
throw new ArgumentNullException("password");
}
// Produce a version 0 (see comment above) text hash.
byte[] salt;
byte[] subkey;
using (var deriveBytes = new Rfc2898DeriveBytes(password, SaltSize, PBKDF2IterCount))
{
salt = deriveBytes.Salt;
subkey = deriveBytes.GetBytes(PBKDF2SubkeyLength);
}
var outputBytes = new byte[1 + SaltSize + PBKDF2SubkeyLength];
Buffer.BlockCopy(salt, 0, outputBytes, 1, SaltSize);
Buffer.BlockCopy(subkey, 0, outputBytes, 1 + SaltSize, PBKDF2SubkeyLength);
return Convert.ToBase64String(outputBytes);
}
I would like to avoid having to add ASP.NET Identity as a dependency to this project hence why I would like to hash the password manually.
I would recommend you to use SimpleCrypto
This is how I've used that in a project I believe this will help you. One can add this DLL from nuget
[HttpPost]
public ActionResult Register(RegisterViewModel model)
{
try
{
if (ModelState.IsValid)
{
{
var crypto = new SimpleCrypto.PBKDF2();
var encrypPass = crypto.Compute(model.Password);
var newUser = db.Users.Create();
newUser.Email = model.Email;
newUser.Password = encrypPass;
newUser.PasswordSalt = crypto.Salt;
// newUser.Name = model.UserName;
newUser.Username = model.UserName;
//newUser.AddedBy = model.;
db.Users.Add(newUser);
db.SaveChanges();
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "");
}
}
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}
return View();
}
Your valid check at login will be like this
private bool IsValid(string email, string password)
{
var crypto = new SimpleCrypto.PBKDF2();
bool isValid = false;
{
var user = db.Users.FirstOrDefault(u => u.Email == email);
if (user != null)
{
if (user.Password == crypto.Compute(password, user.PasswordSalt))
{
isValid = true;
}
}
}
return isValid;
}

Mobile App GetIdentityAsync no value

I have this code from Azure Services Mobile App, API custom controller. The result always the same "1:1". I test with all identity providers, google, facebook, twitter, and Microsoft Account, except AD. I think the problem is the call to GetIdentityAsync. Can anyone help me? Thanks
[HttpGet]
public async Task<string> GetIdentityInfo()
{
var user = (MobileAppUser)this.User;
string str = "";
string Provider = "YES", UserId = "NO";
try
{
if (user != null)
{
Provider = "1"; UserId = "1";
var microsoftCredentials = await user.GetIdentityAsync<MicrosoftAccountCredentials>();
if (microsoftCredentials != null && microsoftCredentials.Claims != null)
{
Provider = "MICROSOFT";
UserId = microsoftCredentials.UserId;
}
Provider = "2"; UserId = "2";
var googleCredentials = await user.GetIdentityAsync<GoogleCredentials>();
if (googleCredentials != null && googleCredentials.Claims != null)
{
Provider = "GOOGLE";
UserId = googleCredentials.UserId;
}
Provider = "3"; UserId = "3";
var facebookCredentials = await user.GetIdentityAsync<FacebookCredentials>();
if (facebookCredentials != null && facebookCredentials.Claims != null)
{
Provider = "FACEBOOK";
UserId = facebookCredentials.UserId;
}
Provider = "4"; UserId = "4";
var twitterCredentials = await user.GetIdentityAsync<TwitterCredentials>();
if (twitterCredentials != null && twitterCredentials.Claims != null)
{
Provider = "TWITTER";
UserId = twitterCredentials.UserId;
}
}
else
{
Provider = "NONE"; UserId = "NULL";
}
}
catch (Exception ex)
{
str = "ERROR";
}
finally
{
str = Provider + ":" + UserId;
}
return str;
}
We receive support from Microsoft Support Engineer Adrian Fernandez Garcia, and send an example that worked OK. The unique difference was that EMA_RuntimeUrl must be created manually in mobile app in azure portal in Application Properties, and assigned to Gateway address.
Actually this value is created automatically and don't have to create it manually.
This gave us the error URIFormat NULL value.
All is working OK now.
Thanks to Microsoft for the support.

I want to send free form native query output to excel using a WebGrid

First I need to explain my problem, I have a native query application where someone types in "Select .... this and that" and the output is currently displayed in a grid that is paginated and I have been asked to add a button that will export the data to excel directly from an untyped datastream. my current code that I've found uses a grid and still doesn't prompt me to download a .xls file for some reason.
[Authorize(Roles = "Portal administrator")]
public void ExportExcel(NativeQueryVM model, int? page, string sort)
{
List<Dictionary<string, object>> result = null;
String vartimedate = DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss");
try
{
var user = Membership.GetUser();
var grid = new System.Web.UI.WebControls.GridView();
if (page == null && sort == null)
{
if (model.QueryText.ToUpper().StartsWith("SELECT"))
{
UserQueryInput queryinput = new UserQueryInput();
queryinput.DatabaseId = model.selectedDatabase;
queryinput.QueryText = model.QueryText;
result = lookupProvider.GetSetNativeQuery((Guid)user.ProviderUserKey, user.UserName, queryinput, "Set");
model.QueryResultData = result;
ViewBag.SubmitType = "Select";
CreateDynamicResult(model.QueryResultData);
if (model == null || model.QueryResultData.Count == 0)
{
ViewBag.ResultMessage = "No Results Found";
}
else
{
WebGrid wd = new WebGrid(source: ViewBag.DynamicResult, canPage: false, canSort: false );
string griddata = wd.GetHtml().ToString();
string attachment = "attachment; filename=NativeQuery" + vartimedate + ".xls";
Response.ClearContent();
Response.AddHeader("content-disposition", attachment);
Response.ContentType = "application/excel";
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
Response.Write(griddata);
Response.End();
}
}
}
else
{ //This part should come when page or sort is not null for Select. Should not be executed other than SELECT
result = lookupProvider.GetSetNativeQuery((Guid)user.ProviderUserKey, user.UserName, null, "Get");
model.QueryResultData = result;
ViewBag.SubmitType = "Select";
CreateDynamicResult(model.QueryResultData);
if (model == null || model.QueryResultData.Count == 0)
{
ViewBag.ResultMessage = "No Results Found";
}
else
{
}
}
}
catch (Exception ex)
{
logger.Log(new LogMessage()
.ForMethod("SubmitQuery")
.WithContext(Environment.MachineName)
.WithException(ex)
.WithDescription("An error occurred while submiting query to get result"));
}
}
Hi all that answered this problem, and I've found the answer and issues reside outside of the code that I've entered into the question. Jquery was intercepting the output of my file stream and on the other hand, if the button was created with runat=server the model is out of scope and the main part of the solution involved saving the model to a session and pulling it back in.
Thanks for your assistance all...
How are you calling this void function? The return paths include setting a ViewBag property with an error message along with modifying the response. It smells of bad design.
I'd create a hyperlink that links to a #Url.Action for something like this. Note that you'd need to return a FileContentResult with the data UTF8-encoded rather than modifying the Response directly:
public async Task<ActionResult> Test()
{
WebGrid wd = new WebGrid(source: ViewBag.DynamicResult, canPage: false, canSort: false );
string griddata = wd.GetHtml().ToString();
string attachment = "attachment; filename=NativeQuery" + vartimedate + ".xls";
Response.ClearContent();
Response.AddHeader("content-disposition", attachment);
Response.ContentType = "application/excel";
byte[] buffer = System.Text.UTF8Encoding.UTF8.GetBytes(griddata);
return File(buffer, "application/octet-stream");
}

Resources