Websecurity.CreateUserAndAccount on Azure doesn't work - asp.net-mvc

I have a method that registers a new user using WebSecurity.CreateUserAndAccount(model.UserName, model.Password) The problem is that in the UserProfile model I have added a GUID Key. On my local machine this just populates an empty Guid when I call this method. On azure however, I get the following error:
System.Data.SqlClient.SqlException (0x80131904): Cannot insert the value NULL into column 'Key', table 'Scheduler.dbo.UserProfile'; column does not allow nulls. INSERT fails.
Now, I've tried to generate a new GUID in the constructor of the model, manually have the Set{} generate a new GUID and I get the same error.
When I try to use the CreateUserAndAccount overload like:
WebSecurity.CreateUserAndAccount(model.UserName, model.Password, new { Key = Guid.NewGuid() });
I get the following syntax error (run time):
Incorrect syntax near the keyword 'Key'.
I've spent a good part of the morning trying to figure this out and I just can't. By the way all of the above methods still result in an empty GUID 00000000-0000-0000-0000-000000000000 and the overload gives me syntax error on my local machine.

"Key" is a reserved word in SQL, it should be used in brackets like this [Key]
Since you don't have control on how WebSecurity generate the SQL query then your only option is to rename it to something like UserKey

Related

Asp.Net Identity external login issue

I have a problem using Asp.Net Identity.
I have an ASP.NET MVC 5 application where there is an ApplicationUser class which is inherited from IdentityUser class. I am not using separate AuthenticationContext, I have just one DbContext.
I am working on the website authentication and I want to use Facebook login in my App.
I applied the necessary settings and when I click on the facebook button I get this exception in the AccountController.ExternalLoginCallback method.
> Invalid column name 'User_Id'. Description: An unhandled exception
> occurred during the execution of the current web request. Please
> review the stack trace for more information about the error and where
> it originated in the code.
>
> Exception Details: System.Data.SqlClient.SqlException: Invalid column
> name 'User_Id'.
>
> Source Error:
>
>
>
> Line 220: Line 221: // Sign in the user with this external
> login provider if the user already has a login Line 222:
> var user = await UserManager.FindAsync(loginInfo.Login); Line 223:
> if (user != null) Line 224: {
It's really strange for me because there is not user_id column in database.
I use Code First Migration and I know when a class has a complex property but does not have the foreign key property the Code First Migration will generate foreign key property in the db.
So, I am lost, I tried to debug it but I dont have any result.
Anybody can help me?
This doesn't have anything to do with external login. Somewhere, something is looking for a User_Id column, which of course doesn't exist because that's the error you're getting.
That format of column name is generally from a code-first conventions-based foreign key, i.e. there's a class that has public virtual ApplicationUser User { get; set; } and no explicit id property for storing that relatonship. As a result, Entity Framework will create and try to use a column in the table of the format [NavigationPropertyName]_[EntityIdProperty]: in this case, User_Id.
Normally, you wouldn't get far enough to get this type of error as Entity Framework would raise an exception first telling you that you needed to run a migration on your database. However, it's possible that you either changed from/to an explicit foreign key property or are using something like database-first, with migrations disabled.
Basically, you just need to find what entity has a navigation property to ApplicationUser without a corresponding property to hold the key, and then either add a User_Id column to the table that corresponds to that entity, or correct the code so that it looks for the right column name.

Error in breeze using EF 5 and calling stored procedure

Getting an error client side with breeze: "Cannot call method 'map' of undefined" when trying to pull over some data. The difference between this action and one that works is that this action is calling a stored procedure and returning ObjectResult<T> instead of DbSet<T>.
Might this be why I get an error? Using Chrome Developer tools, I do see that the breeze controller is returning json data.
I have created a complex model type in the edmx for mapping the rows returned from the stored procedure.
The action in the breeze controller has a return type of IEnumerable<T>.
I experienced the same error when using an EF complex type. A workaround was to create a view in my database instead of using a complex type, set the stored procedure to return a type of the new view which had a primary key and then it worked. It would seem that breeze requires entities to have a primary key defined.
Hm... not quite sure what is happening, so just guessing here, but try adding an AsQueryable() to the result returned, and changing the result type to a IQueryable.
We don't have any stored proc tests for breeze yet, but this is impetus for me to add some :)
I had the very same issue, but thank God I figured out a solution. Instead of using a stored procedure, you should use a view, as Breeze recognizes views as DbSet<T>, just like tables. Say you have a SQL server table that contains two tables Customers and Orders.
Customers (**CustomerId**, FirstName, LastName)
Orders (OrderId, #CustomerId, OrderDate, OrderTotal)
Now, say you want a query that returns orders by CustomerId. Usually, you would do that in a stored procedure, but as I said, you need to use a view instead. So the query will look like this in the view.
Select o.OrderId, c.CustomerId, o.OrderDate, o.OrderTotal
from dbo.Orders o inner join dbo.Customers c on c.CustomerId = o.CustomerId
Notice there is no filtering (where ...). So:
i. Create a [general] view that includes the filtering key(s) and name it, say, OrdersByCustomers
ii. Add the OrdersByCustomers view to the entity model in your VS project
iii. Add the entity to the Breeze controller, as such:
public IQueryable<OrdersByCustomers> OrdersByCustomerId(int id)
{
return _contextProvider.Context.OrdersByCustomers
.Where(r => r.CustomerId == id);
}
Notice the .Where(r => r.CustomerId == id) filter. We could do it in the data service file, but because we want the user to see only his personal data, we need to filter from the server so it only returns his data.
iv. Now, that the entity is set in the controller, you may invoke it in the data service file, as such:
var getOrdersByCustomerId = function(orderObservable, id)
{
var query = breeze.EntityQuery.from('OrdersByCustomerId')
.WithParameters({ CustomerId: id });
return manager.executeQuery(query)
.then(function(data) {
if (orderObservable) orderObservable(data.results);
}
.fail(function(e) {
logError('Retrieve Data Failed');
}
}
v. You probably know what to do next from here.
Hope it helps.

How to get primary key field name for null EntityReference?

I've made the following function to assign value to a foreign key reference (I know, it's dirty and does not work for compound keys):
void setFk(dynamic tbl,object id){
var path=db.DefaultContainerName+"."+tbl.TargetRoleName;
var ret=new System.Data.EntityKey(path, tbl.RelationshipSet.ElementType.RelationshipEndMembers[0].GetEntityType().KeyMembers[0].Name, id);
tbl.EntityKey=ret;
}
which I want to invoke by this: setFk(newRec.WorkItemsReference,src.WorkItemsId)
The problem is that it does not work for newly created object newRec because tbl.EntityKey and tbl.RelationshipSet are both null.
One route that I see is to get tbl.GetType() and somehow locate Id column from there. If this is the right route then how ?
Any other route ?
My goal was not to pass more arguments into setFk function because it's supposed to be sufficient with 2 arguments and would lead to duplication of entity name.

Error while querying Breeze with predicate on DateTimeOffset column

I am trying to query my entity with a predicate on a DateTimeOffset column, but getting a 500 error response from the Breeze.WebApi. The error message is
Unable to perform operation: leon types:System.Nullable`1[System.DateTimeOffset], System.DateTime
The uri I see produced is something like
http://localhost:49800/api/Breeze Orders?$filter=LocalDateTime%20le%20datetime'2013-03-03T00%3A00%3A00.000Z'
What is working:
I can query on other DateTime, text columns
I can save new data into my 'LocalDateTime' field
The full error response from the query is:
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Unable to perform operation: leon types:System.Nullable`1[System.DateTimeOffset], System.DateTime
</ExceptionMessage>
<ExceptionType>System.Exception</ExceptionType>
<StackTrace>
at Breeze.WebApi.ParseTreeVisitor.CoerceTypes(String operatorName, Expression& leftExpr, Expression& rightExpr) at Breeze.WebApi.ParseTreeVisitor.VisitBinary(ParseTreeNode node, String operatorName, Expression leftExpr, Expression rightExpr) at Breeze.WebApi.ParseTreeVisitor.VisitNode(ParseTreeNode node) at Breeze.WebApi.ParseTreeVisitor.Parse(Type rootType, ParseTreeNode node) at Breeze.WebApi.ExpressionTreeBuilder.Parse(Type rootType, String source) at Breeze.WebApi.ODataActionFilter.BuildFilterFunc(String filterQueryString, Type elementType) at Breeze.WebApi.ODataActionFilter.OnActionExecuted(HttpActionExecutedContext actionExecutedContext) at System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecuted(HttpActionContext actionContext, HttpResponseMessage response, Exception exception) at System.Web.Http.Filters.ActionFilterAttribute.<>c__DisplayClass2.<System.Web.Http.Filters.IActionFilter.ExecuteActionFilterAsync>b__0(HttpResponseMessage response) at System.Threading.Tasks.TaskHelpersExtensions.<>c__DisplayClass41`2.<Then>b__40(Task`1 t) at System.Threading.Tasks.TaskHelpersExtensions.ThenImpl[TTask,TOuterResult](TTask task, Func`2 continuation, CancellationToken cancellationToken, Boolean runSynchronously)
</StackTrace>
</Error>
.
EDIT
Getting there, but not quite. After installing Breeze 1.2.8 the client is now generating correctly typed uri e.g.
http://localhost:49800/api/Breeze/Orders?$filter=LocalDateTime%20ge%20datetimeoffset'2013-01-01T11%3A00%3A00.000Z'
In my case using setEntityTypeForResourceName to fix the entity type isnt needed. The above uri still gives me the error:
Unable to perform operation: leon types:System.Nullable`1[System.DateTimeOffset], System.DateTimeOffset
Changing my server side model from
public Nullable<System.DateTimeOffset> LocalDateTime { get; set; }
to
public System.DateTimeOffset LocalDateTime { get; set; }
allows my uri to work.
So can we please have a fix for nullable DateTimeOffset.
This is fixed in v 1.2.7. Please post back if you still see the error.
--- Further information ---
There have been several posts since 1.2.7 indicating that this error was still occuring. It turns out that the issue is NOT that breeze doesn't understand 'dataTimeOffsets'. It is that breeze is very forgiving of incorrect EntityType/Resource name mappings in queries except in the case of queries involving 'DateTimeOffsets'. This post is a bit long, so if you just need the fix, read the last paragraph.
The "Unable to perform operation: ... " error occurs when executing a query against a dateTimeOffset property when the resource name declared in the query ( the value in the 'from' clause) cannot be mapped to an existing entityType name (defined in metadata).
If breeze can find an entity type that maps to the resource name declared in the query, it uses the metadata for that entityType to validate the query and create an OData filter string. However, if it can't find a matching entity type, which is a perfectly acceptable condition because some 'resourceName's will not map to entities, it tries to infer the datatypes involved in any query clauses by looking at any constant parameters involved in the query and using their datatype. The problem is that a javascript date object can be mapped to either a .NET 'DateTime' or a 'DateTimeOffset' and Breeze can only pick one and in this case picks the 'wrong' one.
This kind of mismapping does not cause problems when data is returned from a query because breeze only uses the entity type of the query to validate and construct an appropriate OData filter string. Data returned from any query is inspected to determine the entityTypes of each item returned so the resourceName/entityType mapping is not needed. ( A single query may return multiple entity types because of the use of 'expand' or 'select' clauses.)
The root cause of the mapping issue involves the map of resource names to entity types that breeze keeps in each MetadataStore. This mapping is available via the MetadataStore.getEntityTypeNameForResourceName and MetadataStore.setEntityTypeForResourceName methods. When using Entity framework metadata, breeze assumes that Entity Framework 'EntitySet' names correspond to 'resourceNames'. This assumption is what is causing the problem. If you query a 'resourceName' that is different from one of your EntitySet names, Breeze does not know the corresponding 'entity Type' and falls back on inferring the datatypes used in the query, instead of using the 'entity Type' metadata.
There are two fairly simple fixes, either of which work.
1) Use the MetadataStore.setEntityTypeForResourceName method to map your resource names to your entity types. Note that you can have as many resource names as you like mapped to the same entity type.
2) Name your methods ( that correspond to resource names) to the names of the corresponding EntitySet defined in EF and not the name of the type that is returned. A common convention is that EntitySet names ( and hence resource names) are pluralized, whereas EntityType names are usually singular. i.e. 'Customers' is a resource name and 'Customer' is the EntityType

Insert fails on Code First whith non-identity id key

I have defined a model class with an ID column set as [Key], on an existing database table. the table has the field defined as primary key, int, not null. It is NOT and identity column.
When creating a new record in code, I am setting the ID column (to an unique value) in code before calling the SaveChanges() method.
The method returns with the error:
Cannot insert the value NULL into column 'xxx_id', table
'xxx.dbo.xxxxxx'; column does not allow nulls. INSERT fails. The
statement has been terminated.
It seems that EF assumes that the ID column is an Identity column and therefore doesn't pass the ID in the SQL call to the database.
Is there a way to define the ID column to tell EF that is it not an Identity column and to pass the value in the SQL call
You need to specify the DatabaseGeneratedOption for the property. In this case, the DatabaseGeneratedOption should be None.
See: http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.databasegeneratedoption%28v=vs.103%29.aspx
I have usually done this with fluent coniguration like:
Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
.. but it looks like this can also be specified with an attribute. See http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.databasegeneratedoption%28v=vs.103%29.aspx
[DatabaseGenerated(DatabaseGeneratedOption.None)]

Resources