Wednesday, May 16, 2012
Which property caused "System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details." exception?
Sometimes when using ASP.NET MVC 3 / 4 with Entity Framework it can be difficult to see exactly which property is causing issues when db.SaveChanges() is called.
If you wrap the db.SaveChanges() in an appropriate try {} catch {} block whilst debugging (see below) each property in conflict will be written to your debug console which is much more helpful in finding and resolving the problem!
Don't forget to remove the try catch block after your debugging session though otherwise exceptions will be swallowed and disappear in a live environment which will then hinder further debugging efforts!
[Authorize(Roles = "SomeRole")]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(string SomethingsName)
if (ModelState.IsValid)
{
db.Something.Add(new Something()
{
Id = Guid.NewGuid()
,
Name = SomethingsName
});
try
{
db.SaveChanges();
}
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
Debug.WriteLine("Property: {0} Error: {1}",
validationError.PropertyName,validationError.ErrorMessage);
}
}
}
}
return RedirectToAction("Index");
}
Monday, April 23, 2012
ASP.NET MVC 3 Generating an ActionLink in the controller - Html.ActionLink Equivalent
In these instances such as creating links for a wysiwyg editor or adding a link into an email it is preferable to have the system generate it with the appropriate protocol http/https and/or a port number if you're running locally. To this end I did some digging and put together the following little code snippet which does eactly that!
I thought I'd share it here to save me having to look it up again in the future!
string absoluteAction = string.Format("{0}://{1}{2}",
Url.RequestContext.HttpContext.Request.Url.Scheme,
Url.RequestContext.HttpContext.Request.Url.Authority,
Url.Action("ActionName", "ControllerName", new {Id = "Data"}));
Wednesday, April 18, 2012
MVC 3 ModelState Validation after Postback - Page.Validate() equivalent
However I've been working on WebForms for so long that I'm finding more than a few stumbling blocks as I grapple my way up the learning curve. One such hurdle was "How do I re-validate a model after its been posted back to the server". The scenario being I want a user to type a plain text password into a form which is required but not persisted - I used [NotMapped] DataAnnotation attribute in the model definition to get this bit done.
Following that on postback I need to create a Salt (required and persisted) and a PasswordHash (required and persisted). Trouble was, I originally had the Salt and Hash properties within my if (ModelState.IsValid) statement.
The Model was at this point invalid because no password hash or salt had been created yet. "Easy" I thought simply elevate the property assignments above the if condition. No luck (but along the right lines) as the properties were now filled but I needed to Re-Validate the model, no Page.Validate() to rely upon at this point so I did some digging. As it turns out you simply need to call two methods (below) and they are roughly equivalent to what a WebForms guy would consider to be Page.Validate().
p.Salt = CreateSalt(36);
p.PasswordHash = GenerateSaltedHash(UTF8.GetBytes(p.Password), p.Salt);
ModelState.Clear();
TryValidateModel(model);
if (ModelState.IsValid)
{
p.Id = Guid.NewGuid();
db.People.Add(p);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(person);
Saturday, March 03, 2012
Grow your sector knowledge using Twitter and Conferences
I've been following Microsoft development for years now and the advent of twitter gave me a brilliant insight into Microsoft developers thoughts and keeps me abreast of current feeling about technology by those developing it. For years i used Google Reader and added blogs and such forth to achieve the same result but it was must less immediate and much more in-depth.
This week has been a great week on twitter for me keeping up with what's going on at the MVP Conference (still not quite made it to MVP myself but that's all part of my life time goals plan ... ). OK so here a really obvious tip that only just occurred to m,e (stupid) if I hit the #mvp12 link in twitter and then hit the people link - presto a complete list of everyone who was at MVP and who is also on twitter - amazing - all the people i need to follow in one place:
https://twitter.com/#!/search/users/%23mvp12
I went through and more than quadrupled the amount of people I followed BUT hopefully this will give me an excellent view into what's happening going forward!
The same technique should work for any industry and any conference so if you're not sure who to follow and who's making noise in your industry target a conference and away you go!
Wednesday, February 29, 2012
ASP.NET Location Node in web.config
The location tag within the web config file of your asp.net 4 website allows you to specify a location tag with a path attribute and set "web.config" style setting for just that single location! This is particularly handy if you need to set request upload limits or request validation settings for a particular page that handles file uploads or downloads.
Here is an example which allows for the upload of very large files and allows a URL Encoded filename (with some very odd characters) to be downloaded
This location section should be placed within the <configuration>
Thursday, February 16, 2012
ASP.NET Entity Framework 4.3 - What's my Id???
At this point I figured that there are much smarter people out there that have already solved this problem - I'll just have a look and see how they did it (A good view when standing on the shoulders of giants!).
I fired up visual studio, hit nuget for EF 4.3 updated everything, wrote a very contrived example waited for an exception at which point I'd delve into the code and possibly with a little reflection work out what was going on.
Sadly that's not what happened. I discovered that if you instantiate an instance of an entity manually populate its Id and call save changes it simply quietly adds it to the db with the next available identity and carries on!
Although this may well never actually happen in the real world I thought it was interesting none the less.
If I'm being a complete idiot here please do let me know!
- Class1.cs
namespace FactoryPatternSandbox.Core { public class TestContext : DbContext { public TestContext() : base("name=conn") { } public DbSet<ExampleItem> ExampleItemSet {get; set;} } public class ExampleItem { public int Id { get; set; } public string Text { get; set; } } }Default.aspxpublic partial class Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { using (Core.TestContext context = new Core.TestContext()) { Core.ExampleItem example = new Core.ExampleItem(); // Set Id to a random hard coded int example.Id = 1234; // Set arbitrary text value example.Text = DateTime.Now.ToString(); // Add to context with Id 1234 context.ExampleItemSet.Add(example); // output Id to Literal (Output = 1234) something.Text = example.Id.ToString(); context.SaveChanges(); // At this point the Id *should* have been added to the DB as 1234 // or thrown an exception e.g. CannotAssignIdToNewEntityException() // However checking the DB the item has been added with the next // available Id as per a normal INSERT INTO with an IDENTITY column specification // But its not actually told us (via an exception) that the Id value // has indeed changed so when we call for our random hard coded int // it throws an exception saying there are no items in the collection. Core.ExampleItem exampleFromDb = context.ExampleItemSet.Where(l => l.Id == 1234).Single(); } } }
Monday, January 09, 2012
Manage multiple updates to Data using C#, TSQL and OPENXML in SQL Server
I've used this technique with great success in the past in production systems which require a a "grid" of check-boxes and a single "update" button. This kind of thing usually occurs when you have any X can be related to any Y in a many to many kind of relationship. It comes in especially handy when mapping Users to Roles or that kind of thing. Though it can easily be adapted to manage multiple updates of anything in ONE database hit.
Traditionally this kind of code ends up hitting the database either once per cell in the grid or once per row in the grid because SQL Server doesn't allow arrays of things to be sent to a stored procedure. Database hits are expensive and generally less is better.
My technique leverage's SQL Servers ability to access XML data using the OPENXML keyword. When the grid of check-boxes is submitted we gather together the form collection elements (those check-boxes that have been ticked) and create an XML snippet of the results. This is then passed to SQL Server as a single input representing a set of information. OPENXML is then used inside the stored procedure to convert the XML into a temporary table which is then interrogated and used to update the relationship information that the check box represents.
Below is a link to a visual studio 2010 project that you can download , it contains all the source code for the project please feel free to download and try it for yourself - if you find it useful or have an idea of how it could be improved please leave a comment at the bottom of this page.
I have used MVC 3 and SQL Server as a simple container for the project but the technique is equally valid for any type of project Classic ASP, ASP.NET Web-forms included, so long as the RDBMS supports XML the technique will be valid.
I will refrain from a long explanation here as the code is simply one model, controller and view and the database contains just three tables and two stored procedures. If you'd like some more detail please leave a comment at the bottom of the page and Ill update as soon as possible. If I get a lot of feedback then I will flesh out the method some more in a series of posts.
I do hope you find this useful and would love to hear from you!
Project files can be downloaded here and unpacked using 7zip
Thursday, January 05, 2012
disqus.com for @blogger @blogspot comments - really rather good!
This post centres around the ease with which I managed to sign up for and integrate Disqus comments into this very blog. It turns out that to replace the (fairly basic) standard Blogger comments with Disqus is REALLY straightforward. Simply a case of signing up to Disqus pointing it at your blog and clicking the appropriate options.
Disqus accounts are free (though there are paid for versions) and it adds a social edge and more integrated experience if you're a Blogger or a commenter. I original was looking to integrate LiveFyre but it didn't seem to offer the kind of seamless integration and ease for which I was looking (I may be wrong but Disqus just made it so easy!).
Anyway if you're looking for "comments on social steroids) I would definitely recommend it if you're serious about building communities around your content!
http://disqus.com
http://www.livefyre.com/
One last word on LiveFyre if you're looking for something a bit different it works just like other comments managers however it also include live chat as a first-class feature which, when you see it, really is quite impressive!
Wednesday, January 04, 2012
Kodak ESP 5250 All-in-One Colour Ink-jet - Printer / copier / scanner
'via Blog this'
Monday, December 19, 2011
UK Newspaper Front Pages @ Front Pages Today
UK Newspaper Front Pages @ Front Pages Today:
'via Blog this'
One-click Blogging with BlogThis! Chrome Extension | Blogger Buzz
One-click Blogging with BlogThis! Chrome Extension | Blogger Buzz:
'via Blog this'
Wednesday, June 29, 2011
NuGet, SQL CE 4 and CDN - oh my!
NuGet: http://nuget.org/
This is a system for “installing” components into your web application quickly and easily. So lets say your doing a data driven website using SQL CE 4, you’re going to be using jQuery and CSS control adapters. Simply create your new website as per normal fire up NuGet, do a search for jQuery and hit install, do a search for CSSFriendly double click and install. At this point it will have put copies of jQuery and CSS Friendly control adapters straight into your project! Brilliant! Theres LOADS of stuff available ousing NuGet these are only two VERY small example – check it out!
SQL CE 4: http://weblogs.asp.net/scottgu/archive/2011/01/11/vs-2010-sp1-and-sql-ce.aspx
This is an “in site” file based database and needs no server components to run just some webspace supporting .NET 4 – it replaces using MS Access SQLite or PostgresSQL. In order to use it you simply need Visual Studio 2010 sp1 and the SQL CE 4 tooling support installed which can be downloaded from here http://www.microsoft.com/download/en/details.aspx?id=23691 and here http://go.microsoft.com/fwlink/?LinkId=212219 . Then when you right click App_Data select New Item a new option will appear call SQL Server CE 4 – double click it and it will create for you a new database which you can use as per you would access.
SQL CE 4 Membership Provider: http://www.hanselman.com/blog/IntroducingSystemWebProvidersASPNETUniversalProvidersForSessionMembershipRolesAndUserProfileOnSQLCompactAndSQLAzure.aspx
Righty this little gem (provided via NuGet) is a way to use the Membership provider system built into .NET with SQL CE 4 – this is actually really easy to implement in about three step and takes about 5 minutes (I know because I did it yesterday). Once the steps are completed you will be able to use all the Membership functions directly from your new SQL CE 4 database saving you the time and effort of implementing this on small websites each time.
Google and Microsoft CDN
If you’re wanting to include framework such as jQuery jQuery UI and jQuery Validate then consider using a CDN (Content Delivery Network) version. This is basically an include to a file or files stored in the cloud. The advantages are tht you do not have to keep local copies of the files in your project and also that when a request is made when the page loads the file will be delivered from the nearest server to your user which should in theory speed up download times. The google CDN and Microsoft CDNS can be used in tandem so you could include jQuery and jQuery UI files from Google and Validate from Microsoft (I've done this and it works fine) – it’s a good way to keep your file footprint down on small sites:
http://code.google.com/apis/libraries/devguide.html#jquery (Shows links to .js files) for the CSS to be included from CDN also please read the following http://blog.jqueryui.com/2009/03/jquery-ui-17/ (Both CSS and Javascript files are hosted on the Google CDN but only the js files are listed – bit silly however the previous link shows how to include the CSS files as well!)
Microsofts version can be foud here: http://www.asp.net/ajaxlibrary/cdn.ashx (Webpage currently not working!)
Saturday, January 01, 2011
Moving a HTML Table Row
The Javascript function:
<script language="javascript" type="text/javascript">
function move(direction, tableCell) {
// Prepare variables to make code easier to read!
var table = tableCell.parentNode.parentNode;
var rowCount = table.rows.length;
var currentRow = tableCell.parentNode;
var currentRowIndex = currentRow.rowIndex;
// Disallow movement past bounds of table rows!
if (((currentRowIndex == 0) && (direction == 1)) || ((currentRowIndex == (rowCount - 1)) && (direction == 0))) return false;
// Find the Current Row's Sibling we're swapping position with
var newRowIndex = (direction == 0) ? currentRowIndex + 1 : currentRowIndex - 1;
var currentRowSibling = table.rows[newRowIndex];
// loop here foreach cell
for (var cellIndex = 0; cellIndex < currentRow.cells.length; cellIndex++) {
var currentRowSiblingCellHTML = currentRowSibling.cells[cellIndex].innerHTML;
currentRowSibling.cells[cellIndex].innerHTML = currentRow.cells[cellIndex].innerHTML;
currentRow.cells[cellIndex].innerHTML = currentRowSiblingCellHTML;
}
}
</script>
Tuesday, March 30, 2010
Tuesday, February 23, 2010
Monday, February 15, 2010
Down and dirty with Trace Listerners for SOAP Messages
<system.diagnostics>
<trace autoflush="true"/>
<sources>
<source name="System.Net" maxdatasize="1024">
<listeners>
<add name="TraceFile"/>
</listeners>
</source>
<source name="System.Net.Sockets" maxdatasize="1024">
<listeners>
<add name="TraceFile"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add name="TraceFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="trace.log"/>
</sharedListeners>
<switches>
<add name="System.Net" value="Verbose"/>
<add name="System.Net.Sockets" value="Verbose"/>
</switches>
</system.diagnostics>
Friday, November 06, 2009
A simple way to add OnUnload to the body of a page
Page.ClientScript.RegisterStartupScript(typeof(string),"AutoCloseWindow","window.onunload = function () { window.opener.location.href = window.opener.location.href; window.close(); };", true);
Monday, September 14, 2009
Old Skool - Classic ASP ServerVariables List
Tuesday, September 01, 2009
Useful code to properly record and redirect an unhandled exception from Global.asax Application_Error Handler
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
string httpCode = ((HttpException) Server.GetLastError()).GetHttpCode().ToString();
if (HttpContext.Current.Session != null)
{
HttpContext.Current.Session["LastError"] = Server.GetLastError();
Server.ClearError();
}
switch (httpCode)
{
case "404":
Response.Redirect("/Error/Error404.aspx");
break;
default:
Response.Redirect("/Error/Error.aspx");
break;
}
}
Wednesday, August 12, 2009
GridView (non-object/sql DataSource) Paging and Sorting
This is just a quick reminder post about how to do things and in what order to get Paging and Sorting working together on a GridView Control when you’re datasource is NOT a SqlDataSource or ObjectDataSource reference by DataSourceId in the ASPX file but rather a (collection of) POCO objects or other datasource!
.ASPX file
<asp:GridView CssClass="tableStyle1" HeaderStyle-CssClass="bgA" RowStyle-CssClass="bgB"
DataKeyNames="Id" AlternatingRowStyle-CssClass="bgB" AllowPaging="true"
AllowSorting="true" PageSize="50" OnPageIndexChanging="ResultsGrid_PageIndexChanging"
AutoGenerateColumns="false" runat="server" ID="ResultsGrid" OnRowDataBound="ResultsGrid_RowDataBound"
OnSorting="ResultsGrid_Sorting" PagerStyle-ForeColor="White">
<Columns>
<asp:BoundField DataFi
.CS file
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
ViewState["SortExpression"] = "Title";
ViewState["SortDirection"] = "ASC";
}
}
public void ResultsGrid_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
ResultsGrid.PageIndex = e.NewPageIndex;
BindResultGrid();
}
private void BindResultGrid()
{
SqlDataAdapter da = new SqlDataAdapter("ReportingSelect", new SqlConnection(connectionString));
GetSqlParametersForFilter(PrepareFilterTerms(), da.SelectCommand);
DataSet results = new DataSet();
da.Fill(results);
ResultsGrid.DataSource = ApplySorting(results.Tables[0].DefaultView);
ResultsGrid.DataBind();
}
private DataView ApplySorting(DataView dataViewForSorting)
{
dataViewForSorting.Sort = ViewState["SortExpression"].ToString() + " " + ViewState["SortDirection"].ToString();
return dataViewForSorting;
}
public void ResultsGrid_Sorting(object sender, GridViewSortEventArgs e)
{
if (e.SortExpression.ToString() == ViewState["SortExpression"].ToString())
{
if (ViewState["SortDirection"].ToString().StartsWith("ASC"))
{
ViewState["SortDirection"] = "DESC";
}
else
{
ViewState["SortDirection"] = "ASC";
}
}
else
{
ViewState["SortExpression"] = e.SortExpression.ToString();
if (e.SortDirection == SortDirection.Ascending)
{
ViewState["SortDirection"] = "ASC";
}
else
{
ViewState["SortDirection"] = "DESC";
}
}
BindResultGrid();
}