Link to Sql Update Row - asp.net

Ok i need to update field Active to True this is code
public static bool FirstLogin(Guid ActivationCode)
{
using (InfinityNightDataContext data = new InfinityNightDataContext())
{
User user = data.Users.Single(User => User.EmailActivation == ActivationCode);
if (user != null)
{
user.Active = true;
user.Exp = "i HAs here";
data.SubmitChanges();
InstallMembershipCookie(user.UserId, user.Email, user.Password, user.UserType, user.FirstName, user.UserImg, "", true);
return true;
}
else
{
return false;
}
}
}
and after data.SubmitChanges(); i can see the changes on the object user but not in DataBase in other function this works but in this case it's don't work ..
any one know what is the problem?

One possible option (as you haven't said much about your setup): Are you using a local database, or a user instance, i.e. does your connection string contain AttachDbFileName? If so is there another copy of the database in your active bin folder (bin\debug, for instance)? If there is can you attach that to SQL express and see if your change has appeared?

Related

How to enable Security Logging AX2012 (SecurityTasks to SecurityRoles)

I want to log SecurityRole - SecurityTask changes, and since the EeUserRoleChangeLog logs User – SecurityRole changes (for Estonia, but commenting out language detection, it logs also for us here in Holland perfectly). I think that basis can be used to log those changes.
So I first created the table:
EeRoleTaskChangeLog with the following fields:
AddRemove EnumType: AddRemove
ChangedBy EDT: UserID
SecurityRole EDT: RefRecID
SecurityTask EDT: RefRecId
I then noticed that within the class SysSecRole, User-Role changes logging is triggered within method removeFromSelectedUser. So whenever someone changes something from the AOT or the front-end, all these changes are then logged within the EeUserRoleChangeLog.
So I extended SysSecTask with the method removeFromSelectedRole:
public void removeFromSelectedRole()
{
RefRecId SecurityRole;
SysSecTreeTasks taskTree;
SecurityRoleTaskGrant SecurityRoleTaskGrant;
taskTree = tree as SysSecTreeTasks;
securityRole = taskTree.getSecurityRole();
ttsbegin;
EePersonalDataAccessLogging::logRoleTaskChange(recId, 0, securityRole, AddRemove::Remove);
delete_from securityRoleTaskGrant where securityRoleTaskGrant.SecurityRole == securityRole && securityRoleTaskGrant.SecurityTask == recId;
ttscommit;
if (treeControl)
{
tree.deleteTreeItem(treeControl, idx);
}
}
However, it somehow doesn’t recognize the triggers and so it does not fill my table.
I hoped to add a delete/insert trigger to the SecuryRoleTaskGrant systemtable, but this is completely closed, so I have no idea how or where this method can be triggered.
So then I thought as a ‘semi-working’ work around, let’s only log changes made in the front-end, since that already fixes the problem for the regular workers. So I decided to find a similar trigger within Forms, and I found the form SysSecUserAddRoles with method assignRolesToSelectedUser. This method has the following trigger:
if (added)
{
EePersonalDataAccessLogging::logUserRoleChange(secRole.RecId,0, userId, AddRemove::Add);
}
I decided to add this trigger to a Form that allows workers to change Task-Roles: SysSecRoleAddTasks method addTasksFromRole, and somehow this also does not seem to fix the problem. It doesn’t fill the table. I use the following code, and front-end changes are still not logged within my created EeRoleTaskChangeLog table.
public int addTasksFromRole(SecurityRole _role, boolean _recursive = false)
{
SecurityRole childRole;
SecuritySubRole subRole;
SecurityTask task;
SecurityRoleTaskGrant srtGrant;
int nAdded = 0;
RefRecId securityRole;
boolean added;
if (_role.RecId == targetRoleId)
{
return 0;
}
startLengthyOperation();
while select task
join SecurityRole, SecurityTask from srtGrant
where srtGrant.SecurityRole == _role.RecId
&& srtGrant.SecurityTask == task.RecId
{
nAdded += this.addTask(task);
}
if (_recursive)
{
while select childRole
where childRole.RecId != targetRoleId
join SecurityRole, SecuritySubRole from subRole
where subRole.SecuritySubRole == childRole.RecId
&& subRole.SecurityRole == _role.RecId
{
this.addTasksFromRole(childRole, true);
}
}
endLengthyOperation();
if (added) //Added
{
EePersonalDataAccessLogging::logRoleTaskChange(securityTask.RecId,0, securityRole, AddRemove::Add);
}
return nAdded;
}
Why doesn’t this trigger the logging?
Do I need to provide any more information?
The SysSecRoleAddTasks Form has also the addTask method, I tried it here as well, but this again doesn’t trigger the logtable to be filled.
public int addTask(SecurityTask _task, boolean _trialAdd = false)
{
SecurityRoleTaskGrant srtGrant;
int nAdded = 0;
boolean added; //Added
RefRecId securityRole; //Added
select targetRole
where targetRole.RecId == targetRoleId; // make sure in sync
select forupdate srtGrant
where srtGrant.SecurityTask == _task.RecId
&& srtGrant.SecurityRole == targetRoleId;
if (!srtGrant)
{
if (!_trialAdd)
{
ttsbegin;
srtGrant.SecurityTask = _task.RecId;
srtGrant.SecurityRole = targetRoleId;
srtGrant.insert();
nAdded++;
myObjects.insert(_task.RecId, true);
if (added) //Added
{
EePersonalDataAccessLogging::logRoleTaskChange(securityTask.RecId,0, securityRole, AddRemove::Add);
}
ttscommit;
}
else if (targetRoleId != 0)
{
nAdded++;
}
//info('Added task "' + _task.Name + '" (' + int2str(appl.ttsLevel()) + ')');
}
/*
else
{
info('Not adding task "' + _task.Name + '"');
} */
return nAdded;
}
Any suggestions?
This question requires a lot of hands-on debugging I would think to solve, which I'm not sure many posters are going to do unfortunately. Have you tried just using the system's database log?
SecurityRole and SecurityTask are system tables, stored under \System Documentation\Tables\SecurityRole, so I didn't know where to find them in the DB log wizard, but I wrote a manual job that I think should work.
I've only tested it with UserInfo, which is another system table and it appears to have logged changes correctly.
static void AddTablesToDBLog(Args _args)
{
void logTable(TableId _tableId, DatabaseLogType _logType)
{
DatabaseLog dblog;
dblog.logTable = _tableId;
dblog.logField = 0;
dblog.logType = _logType;
dblog.insert();
}
ttsBegin;
logTable(tableNum(SecurityRole), DatabaseLogType::Insert);
logTable(tableNum(SecurityRole), DatabaseLogType::Update);
logTable(tableNum(SecurityRole), DatabaseLogType::Delete);
logTable(tableNum(SecurityTask), DatabaseLogType::Insert);
logTable(tableNum(SecurityTask), DatabaseLogType::Update);
logTable(tableNum(SecurityTask), DatabaseLogType::Delete);
ttsCommit;
SysFlushDatabaseLogSetup::main();
new MenuFunction(menuitemDisplayStr(SysDatabaseLogSetup), MenuItemType::Display).run(null);
info("Done");
}

Obscure Unity Firebase Realtime Database Error: "Custom Run loops are not supported"?

I am currently attemping to build a custom Editor tool for Unity that utilizes the Firebase Realtime Database. This tool would allow someone to right-click on a scene asset in the inspector and select to 'lock' or 'unlock' the scene. Within our Firebase Database, this locking is represented by a dictionary, with each scene name as a key and each value being either "locked" or "unlocked". This funcitonality will be expanded later, but for now, I'm just trying to get things set up so that I can actually connect to and use the Firebase Realtime Database.
I had looked at the Firebase Quickstart Unity project for the Realtime Database (the one that functions like a leaderboard) and saw that it worked fine. I could replace the database URL in the project with the URL for my app's database, and when I entered in values, they appeared inside my realtime database.
So, I based the code for my custom editor script on the code from the quickstart. In fact, I copy-pasted most of it. I will post the script itself, and then describe the errors I receive, as well as the lines that give the errors:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using Firebase;
using Firebase.Unity.Editor;
using Firebase.Database;
[CustomEditor(typeof(SceneAsset))]
[ExecuteInEditMode]
public class SceneLockingEditor : Editor
{
static string sceneName;
DependencyStatus dependencyStatus = DependencyStatus.UnavailableOther;
protected virtual void OnEnable()
{
Debug.Log("OnEnable Called");
sceneName = target.name;
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {
dependencyStatus = task.Result;
if (dependencyStatus == DependencyStatus.Available)
{
InitializeFirebase();
}
else
{
Debug.LogError(
"Could not resolve all Firebase dependencies: " + dependencyStatus);
}
});
}
// Initialize the Firebase database:
protected virtual void InitializeFirebase()
{
Debug.Log("Initializing Firebase");
FirebaseApp app = FirebaseApp.DefaultInstance;
app.SetEditorDatabaseUrl(CENSORING MY DATABASE SORRY);
if (app.Options.DatabaseUrl != null) app.SetEditorDatabaseUrl(app.Options.DatabaseUrl);
}
static TransactionResult SceneLockTransaction(MutableData mutableData)
{
List<object> sceneLocks = mutableData.Value as List<object>;
if (sceneLocks == null)
{
sceneLocks = new List<object>();
}
if(mutableData.ChildrenCount > 0)
{
//Look at every child in the scene locks directory.
foreach (var child in sceneLocks)
{
Debug.Log("Checking next child.");
if (!(child is Dictionary<string, object>))
continue;
//If we find the scene we're looking for...
Debug.Log("Checking if the scene has the name we want");
foreach(string key in ((Dictionary<string, object>)child).Keys)
{
Debug.Log("Key: " + key);
}
if(((Dictionary<string, object>)child).ContainsKey(sceneName))
{
string childLockStatus = (string)((Dictionary<string, object>)child)["lockStatus"];
//If the scene is already locked, just abort.
if (childLockStatus == "locked")
{
Debug.Log("Scene is already locked. Abort.");
return TransactionResult.Abort();
}
else
{
Debug.Log("Scene existed in the database and was not locked. Locking it.");
// If the scene existed in the database but was not locked, we will lock it.
((Dictionary<string, object>)child)[sceneName] = "locked";
// You must set the Value to indicate data at that location has changed.
mutableData.Value = sceneLocks;
return TransactionResult.Success(mutableData);
}
}
}
}
Debug.Log("Scene did not exist in the database. Adding it as locked.");
// If the scene didn't exist in the database before, we will add it as locked.
Dictionary<string, object> newSceneLock = new Dictionary<string, object>();
newSceneLock[sceneName] = "locked";
sceneLocks.Add(newSceneLock);
// You must set the Value to indicate data at that location has changed.
mutableData.Value = sceneLocks;
return TransactionResult.Success(mutableData);
}
static TransactionResult SceneUnlockTransaction(MutableData mutableData)
{
List<object> sceneLocks = mutableData.Value as List<object>;
if (sceneLocks == null)
{
sceneLocks = new List<object>();
}
if (mutableData.ChildrenCount > 0)
{
//Look at every child in the scene locks directory.
foreach (var child in sceneLocks)
{
Debug.Log("Checking next child.");
if (!(child is Dictionary<string, object>))
continue;
//If we find the scene we're looking for...
Debug.Log("Checking if the scene has the name we want");
foreach (string key in ((Dictionary<string, object>)child).Keys)
{
Debug.Log("Key: " + key);
}
if (((Dictionary<string, object>)child).ContainsKey(sceneName))
{
string childLockStatus = (string)((Dictionary<string, object>)child)["lockStatus"];
//If the scene is already locked, just abort.
if (childLockStatus == "unlocked")
{
Debug.Log("Scene is already unlocked. Abort.");
return TransactionResult.Abort();
}
else
{
Debug.Log("Scene existed in the database and was locked. Unlocking it.");
// If the scene existed in the database but was not locked, we will lock it.
((Dictionary<string, object>)child)[sceneName] = "unlocked";
// You must set the Value to indicate data at that location has changed.
mutableData.Value = sceneLocks;
return TransactionResult.Success(mutableData);
}
}
}
}
Debug.Log("Scene did not exist in the database. Adding it as unlocked.");
// If the scene didn't exist in the database before, we will add it as locked.
Dictionary<string, object> newSceneLock = new Dictionary<string, object>();
newSceneLock[sceneName] = "unlocked";
sceneLocks.Add(newSceneLock);
// You must set the Value to indicate data at that location has changed.
mutableData.Value = sceneLocks;
return TransactionResult.Success(mutableData);
}
static public void AddSceneLock()
{
Debug.Log("Attempting to add scene lock to database.");
DatabaseReference reference = FirebaseDatabase.DefaultInstance.GetReference("SceneLocks");
Debug.Log("Running Transaction...");
// Use a transaction to ensure that we do not encounter issues with
// simultaneous updates that otherwise might create more than MaxScores top scores.
reference.RunTransaction(SceneLockTransaction)
.ContinueWith(task => {
if (task.Exception != null)
{
Debug.Log(task.Exception.ToString());
}
else if (task.IsCompleted)
{
Debug.Log("Transaction complete.");
}
});
}
static public void RemoveSceneLock()
{
Debug.Log("Attempting to add scene lock to database.");
DatabaseReference reference = FirebaseDatabase.DefaultInstance.GetReference("SceneLocks");
Debug.Log("Running Transaction...");
// Use a transaction to ensure that we do not encounter issues with
// simultaneous updates that otherwise might create more than MaxScores top scores.
reference.RunTransaction(SceneUnlockTransaction)
.ContinueWith(task => {
if (task.Exception != null)
{
Debug.Log(task.Exception.ToString());
}
else if (task.IsCompleted)
{
Debug.Log("Transaction complete.");
}
});
}
[MenuItem("CONTEXT/SceneAsset/Lock Scene", false, 0)]
public static void LockScene()
{
Debug.Log("LockScene Called for scene " + sceneName + ".");
AddSceneLock();
}
[MenuItem("CONTEXT/SceneAsset/Unlock Scene", false, 0)]
public static void UnlockScene()
{
Debug.Log("UnlockScene Called for scene " + sceneName + ".");
RemoveSceneLock();
}
}
The errors always come from this line:
FirebaseDatabase.DefaultInstance.GetReference("SceneLocks");
Any line that has to do with "FirebaseDatabase.DefaultInstance" will throw one of the following two errors
Error 1:
InvalidOperationException: SyncContext not initialized.
Firebase.Unity.UnitySynchronizationContext.get_Instance ()
Firebase.Platform.PlatformInformation.get_SynchronizationContext ()
Firebase.FirebaseApp.get_ThreadSynchronizationContext ()
Firebase.Database.DotNet.DotNetPlatform+SynchronizationContextTarget..ctor ()
Firebase.Database.DotNet.DotNetPlatform.NewEventTarget (Firebase.Database.Internal.Core.Context c)
Firebase.Database.Internal.Core.Context.EnsureEventTarget ()
Firebase.Database.Internal.Core.Context.InitServices ()
Firebase.Database.Internal.Core.Context.Freeze ()
Firebase.Database.Internal.Core.RepoManager.CreateLocalRepo (Firebase.Database.Internal.Core.Context ctx, Firebase.Database.Internal.Core.RepoInfo info, Firebase.Database.FirebaseDatabase firebaseDatabase)
Firebase.Database.Internal.Core.RepoManager.CreateRepo (Firebase.Database.Internal.Core.Context ctx, Firebase.Database.Internal.Core.RepoInfo info, Firebase.Database.FirebaseDatabase firebaseDatabase)
Firebase.Database.FirebaseDatabase.EnsureRepo ()
Firebase.Database.FirebaseDatabase.get_RootReference ()
SceneLockingEditor.OnInspectorGUI () (at Assets/Bitloft/SCRIPTS/Editor/SceneLockingEditor.cs:37)
UnityEditor.InspectorWindow.DrawEditor (UnityEditor.Editor[] editors, Int32 editorIndex, Boolean rebuildOptimizedGUIBlock, System.Boolean& showImportedObjectBarNext, UnityEngine.Rect& importedObjectBarRect) (at C:/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:1242)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
Error 2:
Exception: Custom Run loops are not supported!
Firebase.Database.Internal.Core.Context.GetExecutorService ()
Firebase.Database.Internal.Core.Context.GetConnectionContext ()
Firebase.Database.Internal.Core.Context.NewPersistentConnection (Firebase.Database.Internal.Connection.HostInfo info, IDelegate delegate_)
Firebase.Database.Internal.Core.Repo..ctor (Firebase.Database.Internal.Core.RepoInfo repoInfo, Firebase.Database.Internal.Core.Context ctx, Firebase.Database.FirebaseDatabase firebaseDatabase)
Firebase.Database.Internal.Core.RepoManager.CreateLocalRepo (Firebase.Database.Internal.Core.Context ctx, Firebase.Database.Internal.Core.RepoInfo info, Firebase.Database.FirebaseDatabase firebaseDatabase)
Firebase.Database.Internal.Core.RepoManager.CreateRepo (Firebase.Database.Internal.Core.Context ctx, Firebase.Database.Internal.Core.RepoInfo info, Firebase.Database.FirebaseDatabase firebaseDatabase)
Firebase.Database.FirebaseDatabase.EnsureRepo ()
Firebase.Database.FirebaseDatabase.get_RootReference ()
SceneLockingEditor.OnInspectorGUI () (at Assets/Bitloft/SCRIPTS/Editor/SceneLockingEditor.cs:37)
UnityEditor.InspectorWindow.DrawEditor (UnityEditor.Editor[] editors, Int32 editorIndex, Boolean rebuildOptimizedGUIBlock, System.Boolean& showImportedObjectBarNext, UnityEngine.Rect& importedObjectBarRect) (at C:/buildslave/unity/build/Editor/Mono/Inspector/InspectorWindow.cs:1242)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
It's always one error or the other, and I can't determine what causes one error to appear rather than the other. Both errors stop whatever operation I'm trying to do on the database, which means I can't interact with my database at all.
I've taken a look at the quickstart projects and watched some videos of people setting up Firebase to work with their projects, and I can't seem to determine what I have messed up during the process. I have imported my google-services.json into the unity project. The quickstart projects worked just fine interacting with my database. It's just this particular script that won't work. I cannot find any mention of these two errors anywhere on Google. I even contacted the official Firebase support and they couldn't give me any advice on what the errors mean or what could be causing them.
I considered one problem might be in my initialization function. Instead of doing:
FirebaseApp app = FirebaseApp.DefaultInstance;
I figured that maybe I am supposed to use FirebaseApp.Create() with a custom name passed in, but that resulted in the same errors being thrown on the same line. I am at a loss for how to proceed with this problem. I don't know of anyone else who has had these particular errors, and I've done very much experimentation with different ways to access the database over the past several days. If anybody has an idea of what I am doing wrong here, or what causes these errors (and, how to fix them), I would really appreciate it.
At first you should initialize firebase with new instance of FirebaseApp with unique name. I do it like this:
FirebaseApp firebaseApp = FirebaseApp.Create(
FirebaseApp.DefaultInstance.Options,
"FIREBASE_EDITOR");
The second is setup references (DatabaseReference, StorageReference etc.) with this firebaseApp instance and use it only after FirebaseApp.CheckAndFixDependenciesAsync()
Overall code will look like this:
public static void Initialize(bool isEditor = false)
{
if (isEditor)
{
FirebaseApp firebaseApp = FirebaseApp.Create(
FirebaseApp.DefaultInstance.Options,
"FIREBASE_EDITOR");
firebaseApp.SetEditorDatabaseUrl("https://project.firebaseio.com/");
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
{
if (task.Result == DependencyStatus.Available)
{
database = FirebaseDatabase.GetInstance(firebaseApp).RootReference;
storage = FirebaseStorage.GetInstance(firebaseApp).RootReference;
auth = FirebaseAuth.GetAuth(firebaseApp);
}
else
{
Debug.LogError(
"Could not resolve all Firebase dependencies: " + task.Result);
}
});
}
else
{
FirebaseApp.DefaultInstance.SetEditorDatabaseUrl("https://project.firebaseio.com/");
database = FirebaseDatabase.DefaultInstance.RootReference;
storage = FirebaseStorage.DefaultInstance.RootReference;
auth = FirebaseAuth.DefaultInstance;
}
IsInitialized = true;
}
I had the same errors. I spent several hours solving this and it worked for me

Picking out Just JSON Data Returned from ASP.NET MVC3 controller Update

I've got data returned from my JavaScript client that just includes the data that has changed. That is, I may have an array with each row containing 10 columns of JSON downloaded, but on the Update, only the data that is returned to me is the data that got updated. On my update, I only want to update those columns that are changed (not all of them).
In other words, I have code like below but because I'm passing in an instance of the "President" class, I have no way of knowing what actually came in on the original JSON.
How can I just update what comes into my MVC3 update method and not all columns. That is, 8 of the columns may not come in and will be null in the "data" parameter passed in. I don't want to wipe out all my data because of that.
[HttpPost]
public JsonResult Update(President data)
{
bool success = false;
string message = "no record found";
if (data != null && data.Id > 0)
{
using (var db = new USPresidentsDb())
{
var rec = db.Presidents.FirstOrDefault(a => a.Id == data.Id);
rec.FirstName = data.FirstName;
db.SaveChanges();
success = true;
message = "Update method called successfully";
}
}
return Json(new
{
data,
success,
message
});
}
rec.FirstName = data.FirstName ?? rec.FirstName;
I would use reflection in this case because the code will be too messy like
if (data.FirstName != null)
rec.FirstName = data.FirstName
.
.
.
and so on for all the fields
Using reflection, it would be easier to do this. See this method
public static void CopyOnlyModifiedData<T>(T source, ref T destination)
{
foreach (var propertyInfo in source.GetType().GetProperties())
{
object value = propertyInfo.GetValue(source, null);
if (value!= null && !value.GetType().IsValueType)
{
destination.GetType().GetProperty(propertyInfo.Name, value.GetType()).SetValue(destination, value, null);
}
}
}
USAGE
CopyOnlyModifiedData<President>(data, ref rec);
Please mind that, this won't work for value type properties.

How to get a diff of pending changes to a model in ASP.NET MVC 2

I am working on an ASP.Net MVC app and I want to show a confirmation page after the user edits some data. What I would like to show is a list of the pending changes that the user made to the model.
For example,
Are you sure you want to make the following changes:
FieldName:
Previous Value: XXX
New Value: YYY
I know I can read my stored value from the database and compare it with the POSTed object but I want this to work generally. What would be some good ways to approach this?
To clarify, I am looking for a general way to get a "diff" of the pending changes. I already know how to get the previous and pending changes. Kind of like how TryUpdateModel() can attempt to update any Model with posted values. I'd like a magical GetPendingModelChanges() method that can return a list of something like new PendingChange { Original = "XXX", NewValue = "YYY"} objects.
You might be doing this already but I wouldn't send my model to the view, create a viewmodel. In this case I would map the model data to the viewmodel twice, my viewmodel might contain OrderInput and OrderInputOrig. Then stick OrderInputOrig in hidden fields. On post back you can compare the values and then redirect, if something changed, to a display view with the original and the changes for confirmation.
Maybe something like this:
[HttpPost]
public ActionResult Edit(CustomerInput cutomerInput)
{
var changes = PublicInstancePropertiesEqual(cutomerInput.OriginalCustomer, cutomerInput.Customer);
if (changes != null)
{
cutomerInput.WhatChangeds = changes;
return View("ConfirmChanges", cutomerInput);
}
return View();
}
public ActionResult ConfirmChanges(CustomerInput customerInput)
{
return View(customerInput);
}
from: Comparing object properties in c#
public static Dictionary<string, WhatChanged> PublicInstancePropertiesEqual<T>(T self, T to, params string[] ignore) where T : class
{
Dictionary<string, WhatChanged> changes = null;
if (self != null && to != null)
{
var type = typeof(T);
var ignoreList = new List<string>(ignore);
foreach (System.Reflection.PropertyInfo pi in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
{
if (!ignoreList.Contains(pi.Name))
{
var selfValue = type.GetProperty(pi.Name).GetValue(self, null);
var toValue = type.GetProperty(pi.Name).GetValue(to, null);
if (selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue)))
{
if (changes == null)
changes = new Dictionary<string, WhatChanged>();
changes.Add(pi.Name, new WhatChanged
{
OldValue = selfValue,
NewValue=toValue
});
}
}
}
return changes;
}
return null;
}
Coming in very late here, but I created a library to do this on MVC models and providing "readable" diffs for humans using MVC ModelMetadata:
https://github.com/paultyng/ObjectDiff
It gives me output when I save a Model similar to:
Status: 'Live', was 'Inactive'
Phone: '123-456-7898', was '555-555-5555'
Etc.
use the TempData Dictionary.
TempData["previousValue"];
TempData["newValue"];

Webtest with session-id in url

We have an ASP.Net site that redirects you to a url that shows a session-id. like this:
http://localhost/(S(f3rjcw45q4cqarboeme53lbx))/main.aspx
This id is unique with every request.
Is it possible to test this site using a standard visual studio 2008/2010 webtest? How can I provide the test this data?
I have to call a couple of different pages using that same id.
Yes, it is relatively easy to do this. You will need to create a coded webtest however.
In my example we have a login post that will return the url including the session string.
Just after the we yield the login post request (request3) to the enumerator I call the following.
WebTestRequest request3 = new WebTestRequest((this.Context["WebServer1"].ToString() + "/ICS/Login/English/Login.aspx"));
//more request setup code removed for clarity
yield return request3;
string responseUrl = Context.LastResponse.ResponseUri.AbsoluteUri;
string cookieUrl = GetUrlCookie(responseUrl, this.Context["WebServer1"].ToString(),"/main.aspx");
request3 = null;
Where GetUrlCookie is something like this:
public static string GetUrlCookie(string fullUrl, string webServerUrl, string afterUrlPArt)
{
string result = fullUrl.Substring(webServerUrl.Length);
result = result.Substring(0, result.Length - afterUrlPArt.Length);
return result;
}
Once you have the session cookie string, you can substitute it really easy in any subsequent urls for request/post
e.g.
WebTestRequest request4 = new WebTestRequest((this.Context["WebServer1"].ToString() + cookieUrl + "/mySecureForm.aspx"));
I apologise for my code being so rough, but it was deprecated in my project and is pulled from the first version of the codebase - and for saying it was easy :)
For any load testing, depending on your application, you may have to come up with a stored procedure to call to provide distinct login information each time the test is run.
Note, because the response url cannot be determined ahead of time, for the login post you will have to temporarily turn off the urlValidationEventHandler. To do this I store the validationruleeventhandler in a local variable:
ValidateResponseUrl validationRule1 = new ValidateResponseUrl();
urlValidationRuleEventHandler = new EventHandler<ValidationEventArgs>(validationRule1.Validate);
So can then turn it on and off as I require:
this.ValidateResponse -= urlValidationRuleEventHandler ;
this.ValidateResponse += urlValidationRuleEventHandler ;
The alternative is to code your own such as this (reflectored from the Visual Studio code and changed to be case insensitive.
class QueryLessCaseInsensitiveValidateResponseUrl : ValidateResponseUrl
{
public override void Validate(object sender, ValidationEventArgs e)
{
Uri uri;
string uriString = string.IsNullOrEmpty(e.Request.ExpectedResponseUrl) ? e.Request.Url : e.Request.ExpectedResponseUrl;
if (!Uri.TryCreate(e.Request.Url, UriKind.Absolute, out uri))
{
e.Message = "The request URL could not be parsed";
e.IsValid = false;
}
else
{
Uri uri2;
string leftPart = uri.GetLeftPart(UriPartial.Path);
if (!Uri.TryCreate(uriString, UriKind.Absolute, out uri2))
{
e.Message = "The request URL could not be parsed";
e.IsValid = false;
}
else
{
uriString = uri2.GetLeftPart(UriPartial.Path);
////this removes the query string
//uriString.Substring(0, uriString.Length - uri2.Query.Length);
Uri uritemp = new Uri(uriString);
if (uritemp.Query.Length > 0)
{
string fred = "There is a problem";
}
//changed to ignore case
if (string.Equals(leftPart, uriString, StringComparison.OrdinalIgnoreCase))
{
e.IsValid = true;
}
else
{
e.Message = string.Format("The value of the ExpectedResponseUrl property '{0}' does not equal the actual response URL '{1}'. QueryString parameters were ignored.", new object[] { uriString, leftPart });
e.IsValid = false;
}
}
}
}
}

Resources