I have a requirement where we need a plugin to retrieve a session id from an external system and cache it for a certain time. I use a field on the entity to test if the session is actually being cached. When I refresh the CRM form a couple of times, from the output, it appears there are four versions (at any time consistently) of the same key. I have tried clearing the cache and testing again, but still the same results.
Any help appreciated, thanks in advance.
Output on each refresh of the page:
20170511_125342:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
20170511_125358:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
20170511_125410:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
20170511_125342:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
20170511_125437:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
20170511_125358:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
20170511_125358:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
20170511_125437:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
To accomplish this, I have implemented the following code:
public class SessionPlugin : IPlugin
{
public static readonly ObjectCache Cache = MemoryCache.Default;
private static readonly string _sessionField = "new_sessionid";
#endregion
public void Execute(IServiceProvider serviceProvider)
{
var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
try
{
if (context.MessageName.ToLower() != "retrieve" && context.Stage != 40)
return;
var userId = context.InitiatingUserId.ToString();
// Use the userid as key for the cache
var sessionId = CacheSessionId(userId, GetSessionId(userId));
sessionId = $"{sessionId}:{Cache.Select(kvp => kvp.Key == userId).ToList().Count}:{userId}";
// Assign session id to entity
var entity = (Entity)context.OutputParameters["BusinessEntity"];
if (entity.Contains(_sessionField))
entity[_sessionField] = sessionId;
else
entity.Attributes.Add(new KeyValuePair<string, object>(_sessionField, sessionId));
}
catch (Exception e)
{
throw new InvalidPluginExecutionException(e.Message);
}
}
private string CacheSessionId(string key, string sessionId)
{
// If value is in cache, return it
if (Cache.Contains(key))
return Cache.Get(key).ToString();
var cacheItemPolicy = new CacheItemPolicy()
{
AbsoluteExpiration = ObjectCache.InfiniteAbsoluteExpiration,
Priority = CacheItemPriority.Default
};
Cache.Add(key, sessionId, cacheItemPolicy);
return sessionId;
}
private string GetSessionId(string user)
{
// this will be replaced with the actual call to the external service for the session id
return DateTime.Now.ToString("yyyyMMdd_hhmmss");
}
}
This has been greatly explained by Daryl here: https://stackoverflow.com/a/35643860/7708157
Basically you are not having one MemoryCache instance per whole CRM system, your code simply proves that there are multiple app domains for every plugin, so even static variables stored in such plugin can have multiple values, which you cannot rely on. There is no documentation on MSDN that would explain how the sanboxing works (especially app domains in this case), but certainly using static variables is not a good idea.Of course if you are dealing with online, you cannot be sure if there is only single front-end server or many of them (which will also result in such behaviour)
Class level variables should be limited to configuration information. Using a class level variable as you are doing is not supported. In CRM Online, because of multiple web front ends, a specific request may be executed on a different server by a different instance of the plugin class than another request. Overall, assume CRM is stateless and that unless persisted and retrieved nothing should be assumed to be continuous between plugin executions.
Per the SDK:
The plug-in's Execute method should be written to be stateless because
the constructor is not called for every invocation of the plug-in.
Also, multiple system threads could execute the plug-in at the same
time. All per invocation state information is stored in the context,
so you should not use global variables or attempt to store any data in
member variables for use during the next plug-in invocation unless
that data was obtained from the configuration parameter provided to
the constructor.
Reference: https://msdn.microsoft.com/en-us/library/gg328263.aspx
I am creating a demonstration version of a C# program and I wish it to expire after a month.
// DEMO - Check date
DateTime expires = new DateTime(2016, 3, 16);
expires.AddMonths(2);
var diff = expires.Subtract(DateTime.Now);
if (diff.Days < 0)
{
MessageBox.Show("Demonstration expired.");
return;
}
I am wanting to have the date the compile instead of the hard coded new DateTime(2016, 3, 16);
Is there a compiler directive to give me the current date? Or am I aproaching this the wrong way?
But pre-processor directives are used during compile-time.
That expiration should be implemented using executable code. The issue here is you can hardcode it and hide it as much as possible, but it avid developers can find it and replace the intermediate language and generate a new assembly without the expiration. Actually, there're many other cases where an user can by-pass the whole expiration...
It seems like your best bet should be creating some kind of unique key, store it in your app and check if the whole key is still valid over the wire connecting to some licensing service developed by you.
An alternative solution to hard-coding a date that also offers some flexibility and extensibility could be to host a license file on a web server. For my sample, I used github. Create a well-known file for the application (possibly one for demo and a new one for beta1, etc.). At startup, and possibly periodically, read the file and parse it to determine applicability, timeouts, disable/enable features (like activating a custom warning message), etc.
Now you can ship your demo, put the expire date in the file, change it if needed, etc. This is not the most elegant nor secure solution, but for many use cases for a demo/beta, this might be enough to serve its intended purpose.
Below is a working mock-up of how this might look (omitted error checking and proper cleanup for brevity):
public class LicenseInfo
{
public string Info1 { get; private set; }
public bool IsValid
{
get
{
// todo, add logic here
return true;
}
}
public bool ParseLicense(string data)
{
bool ret = false;
if (data != null)
{
// todo, parse data and set status/attributes/etc
Info1 = data;
ret = true;
}
return ret;
}
}
// could make a static class...
public class License
{
public LicenseInfo GetLicenseInfo()
{
var license = new LicenseInfo();
// todo: create whatever schema you want.
// filename hard-coded per app/version/etc.
// file could contain text/json/etc.
// easy to manage, update, etc.
// extensible.
var uri = "https://raw.githubusercontent.com/korygill/Demo-License/master/StackOverflow-Demo-License.txt";
var request = (HttpWebRequest)HttpWebRequest.Create(uri);
var response = request.GetResponse();
var data = new StreamReader(response.GetResponseStream()).ReadToEnd();
license.ParseLicense(data);
return license;
}
}
class Program
{
static void Main(string[] args)
{
// check if our license if valid
var license = new License();
var licenseInfo = license.GetLicenseInfo();
if (!licenseInfo.IsValid)
{
Console.WriteLine("Sorry...license expired.");
Environment.Exit(1);
}
Console.WriteLine("You have a valid license.");
Console.WriteLine($"{licenseInfo.Info1}");
}
}
I am making a little project that requires me to access one of my email accounts frequently to send emails. With that being said, I obviously know the log-in information ahead of time, and in order to protect the password from being created into a SecureString multiple times, I have created a Singleton class:
public sealed class Sender
{
#region Private Member Variables
private readonly static Sender SingletonSender = new Sender(); // Singleton object
private readonly SecureString password;
private const String defaultEmailAddress = "xxxxxxxxxxxxx";
#endregion
#region Properties
public static Sender ReminderSender
{
get { return SingletonSender; }
}
#endregion
#region Constructors
private unsafe Sender()
{
Char[] passwordCharacters = {/* password characters */};
fixed (Char* pwChars = passwordCharacters)
{
password = new SecureString(pwChars, passwordCharacters.Length);
}
password.MakeReadOnly();
passwordCharacters = null;
}
#endregion
// Additional methods
}
Now, I am wondering if this is the correct way to protect the password from being exposed unnecessarily? Additionally, if anyone has a better strategy to solve this, I would love to hear it. Note, that my goal of this application is to have it deployed on various PC's not just on my own.
Run the code in a web app, and have the various PCs ask the server to run this code on their behalf.
Do you really want to make sure the user's have .NET 4.5? (answer: no)
You could probably get a Rails app on Heroku in less overall time.
By the way, if you are using Gmail, you can put an OAUTH token on the user's machine instead of your password, which you can revoke. It's still a password of sorts, but at least it's not your password.
https://developers.google.com/gmail/oauth_overview
My MVC application allows a subset of users to insert/edit records in a table, and since I'm using Windows authentication I get their samaccountnames "for free" and can insert these in a "Last Updated By" field in the mentioned records.
One of the most important (and frequently used) views in my application will display lists of 50-100 records per page, but I don't want to display their samaccountnames. I want their more user-friendly display names that I want to get from Active Directory.
I've seen several posts here suggesting linking AD to SQL, but that requires installing components on the SQL server which I'd rather not do. Instead, I was thinking of creating the following interface and derived class:
public interface IUserInformationStore
{
UserInformation FindBySamAccountName(string samAccountName)
}
public class ActiveDirectoryStore
{
HashSet<UserInformation> _cache;
public UserInformation FindBySamAccountName(string samAccountName)
{
// Look for samaccountname in _cache and if not found
// retrieve information from AD with DirectorySearcher.
// Store information in _cache and return correct user.
}
My problem now is how to access this information. I was thinking of using Ninject's ToSingleton, but I suspect that might be "Singleton Per Worker process". So maybe the Cache would be a better place for it. But what would be the best way of accessing the object? Static class with static property that checks if it's in the Cache already, initializes it otherwise, and returns the object?
Or is there a completely better way of solving this problem?
I tried 2 solutions eventually:
1
kernel.Bind<IUserRepository>().To<ActiveDirectoryUserRepository>().InSingletonScope().WithConstructorArgument("rootPath", "LDAP://dc=tessdata,dc=no");
public static MvcHtmlString GetDisplayNameSingleton(this HtmlHelper htmlHelper, string samAccountName)
{
var userRepository = DependencyResolver.Current.GetService<IUserRepository>();
return new MvcHtmlString(userRepository != null ? userRepository.FindByUsername(samAccountName).DisplayName : "Ukjent");
}
2
kernel.Bind<IUserRepository>().To<ActiveDirectoryUserRepository>().WithConstructorArgument("rootPath", "LDAP://dc=tessdata,dc=no");
public static MvcHtmlString GetDisplayName(this HtmlHelper htmlHelper, string samAccountName)
{
if (HttpRuntime.Cache["UserRepository"] == null)
{
var newUserRepository = DependencyResolver.Current.GetService<IUserRepository>();
HttpRuntime.Cache.Add("UserRepository", newUserRepository, null, DateTime.MaxValue,
TimeSpan.FromMinutes(20), CacheItemPriority.Default, null);
}
var userRepository = HttpRuntime.Cache["UserRepository"] as IUserRepository;
return new MvcHtmlString(userRepository != null ? userRepository.FindByUsername(samAccountName).DisplayName : "Ukjent");
}
The second method was noticeably faster, especially after the first call when the repository was cached. You get better control over caching too. The first method will stay in memory until the application is restarted.
I'm not sure about best practice in either case though.
Besides using the Single Responsibility Principle, when designing classes for an application one is writing, what should one keep in mind, to keep the code maintainable, reusable and adhere to OOP principles?
I'm finding it hard to design the classes of applications I'm trying to write, because when does one decide what (functionality) goes in which class and whether it should really be in a derived class or there should be an abstract class or interface for this class?
I know this is probably a topic with many answers, but does anyone have any good guidelines (preferably simple) to designing classes and class hierarchies that are simple to maintain and don't make a mess when creating big applications?
EDIT:
When there's classes that have 10 methods and over and have an abstract base class & interfaces which it derives from. Also has 3 Singleton classes referenced globally inside the class and much more. Sounds like it needs a bit of 'refactoring' applied?
Sorry if it's a long example, but you see the problem I'm facing and I want some input on it. Please just look at design, not at technicalities.
I give an example:
I created this class: (a while back)
class ExistingUserLogon : Logon, ILogonUser
{
#region Member Variables
LogonEventArgs _logoneventargs;
LogonData lgndata;
Factory f = Factory.FactoryInstance;
PasswordEncrypt.Collections.AppLoginDataCollection applogindatacollection;
PasswordEncrypt.Collections.SQlLoginDataCollection sqllogindatacollection;
bool? compare;
static ExistingUserLogon existinguserlogon;
PasswordEncrypt.SQLDatabase.DatabaseLogin dblogin;
string databasename = string.Empty;
#endregion
#region Properties
public static ExistingUserLogon ExistingUserLogonInstance
{
get
{
if (existinguserlogon == null)
existinguserlogon = new ExistingUserLogon();
return existinguserlogon;
}
}
public string loginname
{
get;
set;
}
#endregion
#region Contructors
public ExistingUserLogon(bool? compare, LogonData logondata)
{
this.compare = compare;
this.lgndata = logondata;
this.applogindatacollection = f.AppLoginDataCollection;
this.sqllogindatacollection = f.SqlLoginDataCollection;
}
public ExistingUserLogon()
{
this.applogindatacollection = f.AppLoginDataCollection;
this.sqllogindatacollection = f.SqlLoginDataCollection;
}
#endregion
#region Delegates
public delegate void ConnStrCreated( object sender, LogonEventArgs e );
#endregion
#region Events
public event ConnStrCreated ConnectionStringCreated;
#endregion
private void OnConnectionStringCreated( object sender, LogonEventArgs e )
{
if (ConnectionStringCreated != null)
{
ConnectionStringCreated(sender, e);
}
}
public void LoginNewUser()
{
dblogin = new PasswordEncrypt.SQLDatabase.DatabaseLogin();
if (!string.IsNullOrEmpty(loginname))
{
string temp = dblogin.GenerateDBUserName(loginname);
if (temp != "Already Exists")
{
if (compare == true)
{
IterateCollection(lgndata.HahsedUserName.HashedUserName, new Action<string>(OnDatabaseName));
IterateCollection(temp, new Action<bool, string, string>(OnIterateSuccess));
}
}
}
else
{
LogonEventArgs e = new LogonEventArgs();
e.Success = false;
e.ErrorMessage = "Error! No Username";
OnError(this, e);
}
}
private void OnDatabaseName(string name)
{
this.databasename = name;
}
private void OnIterateSuccess( bool succeed, string psw, string userid )
{
if (succeed)
{
// Create connectionstring
ConnectionStringCreator cnstrCreate = ConnectionStringCreator.ConnectionStringInstance;
if (databasename != string.Empty)
{
string conn = ConnectionStringCreator.CreateConnString(databasename, userid, psw);
bool databaseExists;
databaseExists = DataManagementVerification.DoDatabaseExists(conn);
if (databaseExists)
{
FormsTransfer.ConnectionString = conn;
conn = string.Empty;
}
else
{
LogonEventArgs e = new LogonEventArgs();
e.Success = false;
e.ErrorMessage = "Database does not Exist!";
OnError(this, e);
}
//OnConnectionStringCreated(this, e);
// PasswordEncrypt.LINQtoSQL.PasswordDatabase db = new PasswordEncrypt.LINQtoSQL.PasswordDatabase(conn);
/* PasswordEncrypt.LINQtoSQL.EncryptData _encryptdata = new PasswordEncrypt.LINQtoSQL.EncryptData()
{
EncryptID = 1,
IV = "Test",
PrivateKey = "Hello",
PublicKey = "Tony"
};
db.EncryptionData.InsertOnSubmit(_encryptdata);
// db.SubmitChanges();*/
//PasswordEncrypt.LINQtoSQL.Data _data = new PasswordEncrypt.LINQtoSQL.Data()
//{
// EncryptionID = 1,
// Username = "Tbone",
// Password = "worstje",
// IDCol = 2
//};
//db.Data.InsertOnSubmit(_data);
//db.SubmitChanges();
//IEnumerable<PasswordEncrypt.LINQtoSQL.Data> _ddata = db.Data.Where(data => data.Password == "worstje"); ;
//foreach (PasswordEncrypt.LINQtoSQL.Data data in _ddata)
//{
// MessageBox.Show("Data Found: " + data.Username + "," + data.Password);
//}
}
else
{
MessageBox.Show("Found no Database name", "Database name error");
}
}
else
{
// Unable to create connectionstring
}
}
private void IterateCollection( string username, Action<bool, string, string> OnSucceed )
{
bool succeed = false;
dblogin = new PasswordEncrypt.SQLDatabase.DatabaseLogin();
string psw;
string userid;
foreach (KeyValuePair<PasswordEncrypt.Collections.GItem<string>, PasswordEncrypt.Collections.GItem<string>> kv in sqllogindatacollection)
{
List<char> tempa = new List<char>();
List<char> tempb = new List<char>();
tempa = dblogin.GetNumber(username);
tempb = dblogin.GetNumber(kv.Key.Item);
if (tempa.Count == tempb.Count)
{
for (int i = 0; i < tempa.Count ; i++)
{
if (tempa.ElementAt(i).Equals(tempb.ElementAt(i)))
{
if ( i == (tempa.Count -1) )
succeed = true;
continue;
}
else
{
KeyValuePair<PasswordEncrypt.Collections.GItem<string>, PasswordEncrypt.Collections.GItem<string>> last = sqllogindatacollection.Last();
if (kv.Key.Item.Equals(last.Key.Item))
{
MessageBox.Show("Failed to match usernames for Database", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
succeed = false;
// Let GUI Know...
LogonEventArgs e = new LogonEventArgs();
e.Success = succeed;
OnError(this, e);
break;
}
else
{
break;
}
}
}
// MessageBox.Show("Found a sql username match");
}
// Now go execute method to logon into database...
if (succeed)
{
psw = kv.Value.Item;
userid = kv.Key.Item;
OnSucceed(succeed, psw, userid);
}
succeed = false;
}
}
private void IterateCollection(string key, Action<string> OnDatabaseName )
{
foreach (KeyValuePair<PasswordEncrypt.Collections.GItem<string>, PasswordEncrypt.Collections.GItem<string>> kv in applogindatacollection)
{
if (key == kv.Key.Item)
{
MessageBox.Show("Found a match");
OnDatabaseName(kv.Value.Item);
}
else
{
// MessageBox.Show("No Match");
}
}
}
#region Public Methods
public bool? ReadFromRegistry( HashedUsername username, HashedPassword hashedpassword )
{
return RegistryEdit.ReadFromRegistry(username, hashedpassword);
}
public bool WriteToRegistry( HashedUsername username, HashedPassword hashedpassword )
{
return RegistryEdit.WriteToRegistry(username, hashedpassword);
}
public override void Login(TextBox username, TextBox password)
{
base.Login(username, password);
Login(username.Text, password.Text);
}
protected override void Login(string username, string password)
{
base.Login(username, password);
lgndata = base._logondata;
compare = base._regRead;
if (compare == true)
{
loginname = username;
LoginNewUser();
/// on login succeeded let UI class know
_logoneventargs = new LogonEventArgs();
_logoneventargs.Success = true;
OnExistingUserLoggedIn(this, _logoneventargs);
}
else
{
_logoneventargs = new LogonEventArgs();
_logoneventargs.Success = false;
_logoneventargs.ErrorMessage = "Cannot Login this user, please try again.";
OnError(this, _logoneventargs);
}
/// Get username and password for database...
/// to login using correct user data & permissions
/// Login data for database is generated at runtime
/// then by checking if database with such a name exists
/// login...
}
#endregion
}
Hear I post some of sentence that I did take from my favorite book "Architecting Microsoft® .NET Solutions for the Enterprise" that I strongly recommend to read this book even if you’re not a Software Architect.
It Depends
It always depends. As an architect, you are never sure about anything. There's always the possibility that you're missing something. However, the role requires that decisions be made, so you must be able to evaluate all options and make an informed decision, and to do this promptly, when a decision is required. To buy yourself some time and activate your mental processes in the background, first say, "It depends," and then explain why and what the answer depends on. If you are unsure about what a point depends on, the default answer is, "It depends on the context."
Requirements Are Lord Over All
The architect is just one link in the natural chain of actors in a software project. The customer says what he wants. If the customer doesn't know what he wants, someone will be there to prompt him for specifics. The analyst formalizes what the customer wants. The project manager prepares the groundwork for the formally-defined project. The architect gets the bundle of requirements and sorts them out. Developers follow the architect. The database administrator does his best to make the database support the application effectively. Note that the customer leads the chain, and what the customer wants is the law. What the customer wants goes under the name of requirements. Of course, only few customers know what it is they want. So requirements change.
Program to an Interface
Even if you make a living out of implemented code, you should leverage interfaces wherever possible. Repeat with us: "No implementation is possible without an interface." Look around, there's always an interface that can be extracted.
Keep It Simple but Not Simplistic
You know KISS (Keep It Simple, Stupid), right? This is just our customized version. Simple and concise is usually equivalent to great and well done. Aim at simplicity, but give yourself a boundary for the low end of the range. If you go below that lower boundary, your solution will become simplistic. And this is not a good thing.
Inheritance Is About Polymorphism, Not Reuse
Object-oriented programming (OOP) taught us that we should write a class once and reuse it forever and extend it at will. And this is possible thanks to inheritance. Does this naturally extend to class reuse? Reuse is a much subtler concept than you might think at first. Polymorphism is the key aspect of OOP to leverage. Polymorphism means you can use two inherited classes interchangeably. As others have said, "Reuse is a nice side effect to have." But reuse shouldn't be your goal, or put another way, don't reuse a class through inheritance just to reuse the class. It's better to write a new class that more precisely fits the needs than to try to inherit an existing class that wasn't designed for the job.
Not the DAL? Don't Touch SQL Then
Repeat with us: "Separation of concerns. Separation of concerns." Push data access code and details (such as connection strings, commands, and table names) to the corner. Sooner or later, you need to take care of them, but consider business and presentation logic separately from persistence. And if possible, delegate persistence to ad hoc tools such as Object/ Relational Mapper (O/RM) tools.
Maintainability First
If you could pick only one attribute for your software, what would it be? Scalability? Security? Performance? Testability? Usability? For us, it would be none of the above. For us, what comes first is maintainability. Through maintainability, you can achieve anything else at any time.
All User Input Is Evil
You should have heard this already. If there's a way for users to do something wrong, they'll find it. Oh, this sounds like Murphy's Law. Yes, you should have heard this one, too, already.
Post-Mortem Optimization
Donald Knuth said that premature optimization is the root of all software evil. We go even further. Do not optimize the system. Instead, design it for being improved and extended at any time. But focus on pure optimization only when the system is dismissed.
Security and Testability Are by Design
If you're serious about a system attribute, design for it right from the beginning. Security and testability are no exception to this rule, and there's an International Organization for Standardization (ISO) standard that specifically says so.
I hope you this will help you.
Well, aside from keeping the code maintainable, reusable, and adhering to OOP principles... :)
I'd be careful to avoid paralysis of analysis here: if you don't make the right choice between a class, derived class, or interface, for example, that's what refactoring is for. In fact, I'd argue that's the whole point of principles like the SRP - not to make it easy to design everything beforehand, but to make it easy to change things as your requirements grow and change shape, because you can't predict everything beforehand.
A tension exists between designing code to be reusable and just creating something that is usable. Design for reuse where you can, but don't let that get in the way of just implementing the requirements that are right in front of you.
One tip I've heard (courtesy of Spolsky, probably) is: when you need perform an operation in one place, write the code. When you need to perform it in another place, write the code again. When you want to perform the same op in a third place, now it's time to think about refactoring.
Don't try to design a vast, all-encompassing system in the hopes of avoiding change - design code that's resilient to change.
One thing I wish I learned early was to design your code to interact through very simple interfaces rather than massive APIs. I would recommend you even do this internally. Create simple interfaces that interact between your modules. This makes testing SO much easier.
private interface IPerformWork
{
void DoThis(String value);
void DoThat(String value);
}
Remember, the less coupled your code is the better.
Code Smells
Why don't you browse through this question. It may not be C# specific but a lot of it is completely language agnostic.
https://stackoverflow.com/questions/114342/what-are-code-smells-what-is-the-best-way-to-correct-them
There is a good question here on Stackoverflow that discusses C# anti-patterns, and how to avoid them.
You should give it a quick read through; it exposes a lot of things that you may be tempted to do/not realize are wrong, and has suggestions for how to accomplish the same functionality in a more elegant way.
This is one of those things that they rarely teach in schools, and even when they do its usually a contrived example that still doesnt give you a good idea of how to do it.
The bottom line is that there really isnt a good concrete, scientific way to do this, after all computer programming is still very much an art. :)
What I like to do is:
Write a brief outline of what the application is suppose to do, high level stuff in bullet point form
Divide the bullet points up into "required", "optional", "nice-to-have". Where "required" is stuff that must be there to even "demo" and optional is the stuff that basically makes it a complete application in the customers eyes
If required do my drawings, diagrams, UML, specs etc at this point (depends on whats required)
Start writing code. I like to draft out what I am doing in code and start figuring out how things lay out and what functionality needs to be where
Work to an initial prototype (the "required" stuff) once I reach this point I freeze and start looking at where the design is at, and what the feedback is
Start prioritizing refactoring and redesign with fixing issues in the prototype.
Refactor! Redesign and reimplement
Rinse, lather and repeat.
For some things its obvious what goes into which objects, which classes are needed and what designs are working well. For other things it takes an iteration or two to work out the bugs.
I learn something new on ever project, and I find new ways to apply concepts I thought I understood well. Its a constant learning experience, and there is always something to learn.