I'm relatively new to MVC and SQL CE, and I seem to be having a problem with my primary key field. Inside my database I have 'User' table, and that table has a primary key called 'UserId'. I've created a registration page which gets some data from and should then store that data in the database. However, when the form submit button is clicked, the following error is detected:
The column cannot be modified. [ Column name = UserId ]
This is weird because i'm not attempting to UserId value. The code below is my post action for the registration action:
[HttpPost]
public ActionResult Registration(UserModel user)
{
if (ModelState.IsValid)
{
using (var db = new BlogDbContext())
{
var crypto = new SimpleCrypto.PBKDF2();
var encryptPassword = crypto.Compute(user.Password);
var newUser = db.Users.Create();
newUser.Username = user.Username;
newUser.FirstName = user.FirstName;
newUser.LastName = user.LastName;
newUser.Email = user.Email;
newUser.Password = encryptPassword;
newUser.PasswordSalt = crypto.Salt;
newUser.JoinDate = DateTime.Now;
db.Users.Add(newUser);
db.SaveChanges();
return RedirectToAction("Index", "User");
}
}
else
{
ModelState.AddModelError("", "Registration Failure");
}
return View();
}
When I originally created the database using SQL CE in VS 2012, I set the identity option to 'true' believing that this would auto-increment the primary key column. I've looked on SO for similar questions, however, the majority see to include some sort of SQL query, which I haven't delved into yet. Any help will be greatly appreciated.
Related
Basically I am trying to get pagination working when requesting entities of azure table storage. i.e. Press next button gets the next 10 entities & Press previous button gets the previous 10 entities. A relatively close example Gaurav Mantri's Answer. But my question is how do I get the nextPartitionKey and nextRowKey from a HTML button attribute and store in to a array/list in order to keep track of current page so I can get the next/previous items?Code example would be very appreciated.
Thanks!
This is something I have right now which gets a range of data based on pageNumber request
private async Task<List<UserInfo>> queryPage(CloudTable peopleTable, string item, int pageNumber)
{
// Construct the query operation for all customer entities
TableQuery<CustomerEntity> query = new TableQuery<CustomerEntity>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, item));
// Print the fields for each customer.
TableContinuationToken token = null;
//TodoItem data = new TodoItem();
List<UserInfo> data = new List<UserInfo>();
do
{
TableQuerySegment<CustomerEntity> resultSegment = await peopleTable.ExecuteQuerySegmentedAsync(query, token);
token = resultSegment.ContinuationToken;
foreach (CustomerEntity entity in resultSegment.Results)
{
data.Add(new UserInfo
{
// add data
});
}
} while (token != null);
//get a subset of all entity
List<UserInfo> sublist = data.GetRange(0, pageNumber);
return sublist;
}
Managed to solved the problem under Gaurav's help.
Here is the code, not perfect but works.
private async Task<List<UserInfo>> queryPage(CloudTable peopleTable, string item, string NextPartitionKey , string NextRowKey, int itemNumber)
{
// Construct the query operation for all customer entities
TableQuery<CustomerEntity> query = new TableQuery<CustomerEntity>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, item)).Take(itemNumber);
// Print the fields for each customer.
List<UserInfo> data = new List<UserInfo>();
Tabletoken.NextPartitionKey = NextPartitionKey;
Tabletoken.NextRowKey = NextRowKey;
TableQuerySegment<CustomerEntity> resultSegment = await peopleTable.ExecuteQuerySegmentedAsync(query, Tabletoken);
Tabletoken = resultSegment.ContinuationToken;
foreach (CustomerEntity entity in resultSegment.Results)
{
data.Add(new UserInfo
{
//add data
});
}
return data;
}
private TableContinuationToken Tabletoken = new TableContinuationToken();
and declare it use a tuple.
Tuple<List<UserInfo>, string, string > tuple =
new Tuple<List<UserInfo>, string, string>(data, Tabletoken.NextPartitionKey, Tabletoken.NextRowKey);
I have changed the AspNetUser (identity) tabe to only user with the following code.
// Change the name of the table to be Users instead of AspNetUsers
modelBuilder.Entity<IdentityUser>()
.ToTable("Users").Property(p => p.Id).HasColumnName("UserID");
modelBuilder.Entity<ApplicationUser>()
.ToTable("Users").Property(p => p.Id).HasColumnName("UserID");
My application works fine but not my seed. I have this code in Migrations/Configuration.cs
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
var RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
string role = "Admin";
string password = "Password#1234";
//Create Role Admin if it does not exist
if (!RoleManager.RoleExists(role))
{
var roleresult = RoleManager.Create(new IdentityRole(role));
}
//Create Admin users with password=123456
var admin1 = new ApplicationUser();
admin1.UserName = "admin1#admin1.com";
admin1.Email = "admin1#admin1.com";
admin1.EmailConfirmed = true;
UserManager.Create(admin1, password);
UserManager.AddToRole(admin1.Id, role);
context.SaveChanges();
I get the error message "UserId not found". Seems like my UserManager.Create fails.
How can I change my seed code to use the UserID insted of standard Id?
Actually, when you save the user, it does not have an id given yet, you'll have to retrieve the user in between the creation of the user & addToRole:
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
var RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
string role = "Admin";
string password = "Password#1234";
//Create Role Admin if it does not exist
if (!RoleManager.RoleExists(role))
{
var roleresult = RoleManager.Create(new IdentityRole(role));
}
//Create Admin users with password=123456
var admin1 = new ApplicationUser();
admin1.UserName = "admin1#admin1.com";
admin1.Email = "admin1#admin1.com";
admin1.EmailConfirmed = true;
UserManager.Create(admin1, password);
// Refetch user with ID:
dbAdmin1 = context.Users.FirstOrDefault(x => x.UserName == admin1.UserName);
UserManager.AddToRole(dbAdmin1.Id, role);
context.SaveChanges();
I wrote the following function to get the SharePointDocumentLocation records regarding an account or contact. However, even though I provide an id which most definitely has got a SPDL record associated the result of a count on the EntityCollection that is returned is alway 0. Why does my query not return SPDL records?
internal static EntityCollection GetSPDocumentLocation(IOrganizationService service, Guid id)
{
SharePointDocumentLocation spd = new SharePointDocumentLocation();
QueryExpression query = new QueryExpression
{
EntityName = "sharepointdocumentlocation",
ColumnSet = new ColumnSet("sharepointdocumentlocationid"),
Criteria = new FilterExpression
{
Conditions =
{
new ConditionExpression
{
AttributeName = "regardingobjectid",
Operator = ConditionOperator.Equal,
Values = { id }
}
}
}
};
return service.RetrieveMultiple(query);
}
The following code does work
using System;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using System.ServiceModel.Description;
using System.Net;
using Microsoft.Xrm.Sdk.Query;
namespace CRMConsoleTests
{
class Program
{
static void Main(string[] args)
{
ClientCredentials credentials = new ClientCredentials();
credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
Uri orgUri = new Uri("http://localhost/CRMDEV2/XRMServices/2011/Organization.svc");
Uri homeRealmUri = null;
using (OrganizationServiceProxy service = new OrganizationServiceProxy(orgUri, homeRealmUri, credentials, null))
{
//ConditionExpression ce = new ConditionExpression("regardingobjectid", ConditionOperator.Equal, new Guid(""));
QueryExpression qe = new QueryExpression("sharepointdocumentlocation");
qe.ColumnSet = new ColumnSet(new String[] { "sharepointdocumentlocationid", "regardingobjectid" });
//qe.Criteria.AddCondition(ce);
EntityCollection result = service.RetrieveMultiple(qe);
foreach (Entity entity in result.Entities)
{
Console.WriteLine("Results for the first record: ");
SharePointDocumentLocation spd = entity.ToEntity<SharePointDocumentLocation>();
if (spd.RegardingObjectId != null)
{
Console.WriteLine("Id: " + spd.SharePointDocumentLocationId.ToString() + " with RoId: " + spd.RegardingObjectId.Id.ToString());
}
}
Console.ReadLine();
}
}
}
}
It retrieves 4 records, and when I debug the plugincode above it retrieves 3 records.
Everything looks good with your QueryExpression, although I'd write it a little more concise (something like this):
var qe = new QueryExpression(SharePointDocumentLocation.EntityLogicalName){
ColmnSet = new ColumnSet("sharepointdocumentlocationid"),
};
qe.Criteria.AddCondition("regardingobjectid", ConditionOperator.Equal, id);
Because I don't see anything wrong with the QueryExpression that leads me with two guesses.
You're using impersonation on the IOrganizationService and the impersonated user doesn't have rights to the SharePointDocumentLocation. You won't get an error, you just won't get any records returned.
The id you're passing in is incorrect.
I'd remove the Criteria and see how many records you get back. If you don't get all of the records back, you know your issue is with guess #1.
If you get all records, add the regardingobjectid to the ColumnSet and retrieve the first record without any Criteria in the QueryExpression, then call this method passing in the id of the regardingobject you returned. If nothing is received when adding the regardingobjectid constraint, then something else is wrong.
Update
Since this is executing within the delete of the plugin, it must be performing its cascade deletes before your plugin is firing. You can try the Pre-Validation.
Now that I think of it, it must perform the deletion of the cascading entities in the Validation stage, because if one of them is unable to be deleted, the entity itself can't be deleted.
In my current project I need write in a table all values are changed in the application.
Ex. the guy update the UserName, I need put in a table UserName old value "1" new value "2".
I tried use the ObjectStateEntry but this return all fields. I think the FW return all because my code.
public USER Save(USER obj)
{
using(TPPTEntities db = new TPPTEntities())
{
db.Connection.Open();
USER o = (from n in db.USERs where n.ID == obj.ID select n).FirstOrDefault();
if (o == null)
{
o = new USER()
{
BruteForce = 0,
Email = obj.Email,
IsBlock = false,
LastLogin = DateTime.Now,
Name = obj.Name,
UserName = obj.UserName,
UserPassword = new byte[0],
};
db.AddToUSERs(o);
}
else
{
o.Email = obj.Email;
o.Name = obj.Name;
o.UserName = obj.UserName;
}
db.SaveChanges();
db.Connection.Close();
}
return obj;
}
A way to get old and new values is this:
var ose = this.ObjectStateManager.GetObjectStateEntry(o.EntityKey);
foreach (string propName in ose.GetModifiedProperties())
{
string.Format("Property '{0}', old value: {1}, new value: {2}",
propName, ose.OriginalValues[propName], ose.CurrentValues[propName]);
}
This is pretty useless, of course, but I'm sure you'll know what to do in the foreach loop to store the changes.
Is this a WCF Service? In that case, the changes will probably never come trough since changes to the Object Graph are made where the Object Context is not available. Consider using Self-Tracking Entities
I am using managed client side object model in sharepoint 2010. And I want to get loginaName of the AssignedTo user in Task list.
In server side object model I use SPFieldUserValue.User.LoginName to get this property but in client side object model FieldUserValue.User does not exists.
How can I resolve this situation ?
Thanks
Here is the code for that. I've taken an example of AssignedTo field from Task list. I hope that helps.
public static User GetUserFromAssignedToField(string siteUrl)
{
// create site context
ClientContext ctx = new ClientContext(siteUrl);
// create web object
Web web = ctx.Web;
ctx.Load(web);
// get Tasks list
List list = ctx.Web.Lists.GetByTitle("Tasks");
ctx.Load(list);
// get list item using Id e.g. updating first item in the list
ListItem targetListItem = list.GetItemById(1);
// Load only the assigned to field from the list item
ctx.Load(targetListItem,
item => item["AssignedTo"]);
ctx.ExecuteQuery();
// create and cast the FieldUserValue from the value
FieldUserValue fuv = (FieldUserValue)targetListItem["AssignedTo"];
Console.WriteLine("Request succeeded. \n\n");
Console.WriteLine("Retrieved user Id is: {0}", fuv.LookupId);
Console.WriteLine("Retrieved login name is: {0}", fuv.LookupValue);
User user = ctx.Web.EnsureUser(fuv.LookupValue);
ctx.Load(user);
ctx.ExecuteQuery();
// display the user's email address.
Consol.writeLine("User Email: " + user.Email);
return user;
}
The fuv.LookupValue may contain the display name, not the login name, so my suggestion is (assuming you have the FieldUserValue - fuv in code (as descibed by #ekhanna):
var userId = fuv.LookupId;
var user = ctx.Web.GetUserById(userId);
ctx.Load(user);
ctx.ExecuteQuery();
You get the column which as the FieldUserValue from the list, once you have that you use the lookup id value and then query against the Sites User Info List. In the example below I cache the results to prevent looking up the same id more than once since the query can be expensive.
private readonly Dictionary<int, string> userNameCache = new Dictionary<int, string>();
public string GetUserName(object user)
{
if (user == null)
{
return string.Empty;
}
var username = string.Empty;
var spUser = user as FieldUserValue;
if (spUser != null)
{
if (!userNameCache.TryGetValue(spUser.LookupId, out username))
{
var userInfoList = context.Web.SiteUserInfoList;
context.Load(userInfoList);
var query = new CamlQuery { ViewXml = "<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='ID' /><Value Type='int'>" + spUser.LookupId + "</Value></Eq></Where></Query></View>" };
var users = userInfoList.GetItems(query);
context.Load(users, items => items.Include(
item => item.Id,
item => item["Name"]));
if (context.TryExecuteQuery())
{
var principal = users.GetById(spUser.LookupId);
context.Load(principal);
context.ExecuteQuery()
username = principal["Name"] as string;
userNameCache.Add(spUser.LookupId, username);
}
}
}
return username;
}
Everything above worked for me, but instead of:
FieldUserValue fuv = (FieldUserValue)targetListItem["AssignedTo"];
I used:
FieldUserValue[] fuv = targetListItem["AssignedTo"] as FieldUserValue[];