/// <summary>
/// This does NOT go into sub objects, only the top level object
/// i.e. if you have a class with a string field, it will trim that string field value
/// but not trim any string fields on sub-objects inside the containing class
/// </summary>
/// <param name="currentObject"></param>
public static void SafeTrimAllStringFields(this object currentObject)
{
if (currentObject == null)
{
return;
}
var type = currentObject.GetType();
var stringFields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(f => f.FieldType == typeof(string));
foreach (var field in stringFields)
{
var value = (string)field.GetValue(currentObject);
if (value != null)
{
field.SetValue(currentObject, value.SafeTrim());
}
}
}
}
public static string SafeTrim(this string value)
{
return value == null ? string.Empty : value.Trim();
}
Category Archives: C#
.Net MVC Controller Get Querystring value from UrlReferrer
var querystringFromUrlReferrer= HttpUtility.ParseQueryString(HttpContext.Request.UrlReferrer.Query); var valueYouWant= querystringFromUrlReferrer["NameOfVarToGetFromQuerystring"];
There you go – very helpful…
Clicking a radio button with Selenium
Here is a little code to find and click the first radio button in a set using Selenium:
var didYouGraduateRadioButtonName = string.Format("{0}{1}{2}", "rb_Graduated[", indexValueToUse, "]"); var rbDidYouGraduate = driver.FindElement(By.Id(didYouGraduateRadioButtonName)); javaScriptExecutor.ExecuteScript("arguments[0].checked = true;", rbDidYouGraduate);
Reading hidden field values with Selenium
I have a need to hide a guid used for an index on a .cshtml so I can get model binding on controls dynamically added with ajax (it’s a long story) (that was a mouthful)
I had a hard time finding the value in the hidden field; as it turns out, you can just get it by the attribute on the Selenium element like this:
IWebElement hiddenIndex = driver.FindElement(By.Id("MyControlName_0__Index")); var indexValueToUse = hiddenIndex.GetAttribute("value");
Implementing reCAPTCHA in a Razor MVC view
Setup in your Google account
You will have to have a Google account to use reCAPTCHA.
Log into the google account you want to tie your reCAPTCHA keys to and navigate to:
https://www.google.com/recaptcha/admin#list
Under the ‘Register a new site’ section of that page,follow the instructions and set up a separate key set for each of your development,test, and production environments – including one specifically for ‘localhost’ or 127.0.0.1 so you can test locally.
Web config changes
Add the public and private keys you just created on the Google site to your web.config:
<add key="ReCaptchaPrivateKey" value="yourPrivateKey"/> <add key="ReCaptchaPublicKey" value="yourPublicKey"/>
HttpGet action in the controller
Add a property for yourPublicKey to your viewmodel and load it from the web.config in the get controller action, passing it into the view.
Changes in the head section
Add this script in the head section of your layout or view page:
<script src="https://www.google.com/recaptcha/api.js?render=@layoutModel.yourPublicKey"></script>
Changes on the .cshtml view page
There are two steps for the view page where you want to display the reCaptcha box:
Add this to the view where you want the reCaptcha box to display:
<div class="g-recaptcha" data-sitekey="@Model.YourPublicKey">
And add this script at the bottom of that view:
<script src='https://www.google.com/recaptcha/api.js'></script>
HttpPost action in the controller
You will need some code in the post action of your controller to hit the Google reCaptcha service and get a response if it appears this is a valid person – something like this:
var response = Request["g-recaptcha-response"]; var reCaptchaSecretKey = ConfigurationManager.AppSettings["yourPrivateKey"]; var webClient = new WebClient(); var resultFromGoogle = webClient.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", reCaptchaSecretKey , response)); var parsedResponseFromGoogle = JObject.Parse(resultFromGoogle); var thisIsARealPersonNotARobot = (bool)parsedResponseFromGoogle.SelectToken("success");
With that result in hand, you can decide how to handle a success or failure.
Gotchas:
I noticed that reCAPTCHA tried to send it’s request through TLS1.1 and our site will not allow it – we require TLS 1.2, so I had to add a directive to force it to only use 1.2 with this setting at the top of the HTTPPost controller action:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Thanks for reading and happy coding,
-Jim
Disable Html.DropDownListFor if only one item in dropdown
@Html.DropDownListFor(m => m.SelectedValue,
new SelectList(Model.CollectionOfItemsForDropdown, "ValueField", "NameField"),
@Model.CollectionOfItemsForDropdown.Count > 1
? (object)new { @class = "form-control", required = "true", }
: new { @class = "form-control", required = "true", disabled = "disabled" })
You have to use the conditional operator here for the anonymous objects because the dropdown list will be disabled if the word ‘disabled’ is rendered in the tag in any way.
NHibernate Session Manager needs HttpContext for NUnit testing
In a codebase I work in, NHibernate needs an HttpContext to get its current session – like this:
public static ISession GetCurrentSession()
{
var context = HttpContext.Current;
var currentSession = context.Items[CurrentSessionKey] as ISession;
...
To get my hands on a session for a NUnit test – I put this in the setup:
HttpContext.Current = new HttpContext(
new HttpRequest(null, "http://tempuri.org", null),
new HttpResponse(null));
Also, I wipe the context in the teardown:
<code>
[TearDown]
public void TearDown()
{
HttpContext.Current = null;
}
</code>
Credit for this goes to Caio Proiete:
http://caioproiete.net/en/fake-mock-httpcontext-without-any-special-mocking-framework/
Downloading a file from MVC controller to .ascx using javascript ajax
Here is a simple way to download a file to a .net user control from a newer MVC controller.
The Controller code:
public FileResult DownloadSweetFile()
{
var downloadDirectory = _appSettings.PathToFile;
var filePathAndName = Path.Combine(downloadDirectory, "MySweetFile.pdf");
var cd = new System.Net.Mime.ContentDisposition
{
FileName = "MySweetFile.pdf",
Inline = false, //NOTE: This forces always prompting the user to download, not open file in the browser
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(filePathAndName, "application/pdf");
}
I used a button on the page to fire the javascript
button type="button" id="btnSweetDownload" onclick="downloadSweetFile();" Click here to download a Sweet File!
(I removed the button tag so this will show correctly)
And here is the javascript to use in the .ascx file:
function downloadSweetFile() {
var url = '/MyControllerName/DownloadSweetFile';
window.location = url;
};
Sending messages from an MVC Controller to toastr.js
Toastr and MVC controllers
I often want to generate a message in an .Net MVC controller class and present that to the user with toastr.
Here is a nice pattern for doing just that using TempData.
The Javascript
In a javascript file that is accessible to all the views that are using toastr:
$(document).ready(function() {
if ($('#success').val()) {
displayMessage($('#success').val(), 'success');
}
if ($('#info').val()) {
displayMessage($('#info').val(), 'info');
}
if ($('#warning').val()) {
displayMessage($('#warning').val(), 'warning');
}
if ($('#error').val()) {
displayMessage($('#error').val(), 'error');
}
});
var displayMessage = function (message, msgType) {
toastr.options = {
“closeButton”: false,
“debug”: false,
“positionClass”: “toast-top-right”,
“onClick”: null,
“showDuration”: “300”,
“hideDuration”: “1000”,
“timeOut”: “8000”,
“extendedTimeOut”: “1000”,
“showEasing”: “swing”,
“hideEasing”: “linear”,
“showMethod”: “fadeIn”,
“hideMethod”: “fadeOut”
};
toastr[msgType](message);
};
The Layout or Master Page
If you are using razor with mvc, you can put this in your _layout:
@Html.Hidden(“success”,@TempData[“success”])
@Html.Hidden(“info”,@TempData[“info”])
@Html.Hidden(“warning”,@TempData[“warning”])
@Html.Hidden(“error”,@TempData[“error”])
On my current project, I am working on an older mixed webforms and mvc site so I put this in the views:
<input type="hidden" value="<%=TempData["success"]%>" id="success" />
<input type="hidden" value="<%=TempData["info"]%>" id="info" />
<input type="hidden" value="<%=TempData["warning"]%>" id="warning" />
<input type="hidden" value="<%=TempData["error"]%>" id="error" />
The Controller Code
You send information back from the controller like this:
TempData["warn"] = "You must see this amazing information in a toast!!!";
Open Visual Studio or Sql Management Studio into another domain
Recently, on a contract I was sitting in the clients office, using their network.
I have a domain login to use but my laptop was part of their domain.
This causes all kinds of fun trying to connect to their databases, etc.
Here are two scripts that helped me attach Visual Studio or Sql Server Management Studio to their domain:
Start Sql Server Management Studio in a different domain:
C:\Windows\System32\runas.exe /user:their_domain\yourusername /netonly “C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\VSShell\Common7\IDE\ssms.exe”
Start visual studio in a different domain:
C:\Windows\System32\runas.exe /user:their_domain\yourusername /netonly “C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe”
You will be prompted for the your domain password when you run these.
Happy coding,
Jim