I'm using the Microsoft XRM SDK to programmatically add an entity. However, each time I run a .Create() command I get the following error:
Required member 'LogicalName' missing for field 'Target'
First time using this service and similar resources in our company are scarce, so not sure what this error means or how to investigate/solve it.
Below is the class I created to handle the XRM communication. I instantiate each of the connection properties in the construtor. Then, in this case, call CreateAgency(AgentTransmission agt). The exception is being thrown in the CreateAgency() method on the .Create(account) method call.
class DynamicsCommunication
{
private Uri OrganizationUri = new Uri("http://devhildy03/xRMDRMu01/XRMServices/2011/Organization.svc");
private ClientCredentials credentials;
private OrganizationServiceProxy servicePoxy;
private Guid accountId;
private Entity account;
public DynamicsCommunication()
{
credentials = new ClientCredentials();
credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
servicePoxy = new OrganizationServiceProxy(OrganizationUri, null, credentials, null);
accountId = Guid.Empty;
}
public string UpdateDynamics(AgentTransmission agt)
{
switch (DeterminAction(agt))
{
case DynamicsAction.Create:
return CreateAgency(agt);
case DynamicsAction.Update:
return UpdateAgency(agt);
default:
return string.Empty;
}
}
private string CreateAgency(AgentTransmission agt)
{
try
{
//Exception is thrown after this command
accountId = servicePoxy.Create(CreateAccount(agt));
if (accountId != Guid.Empty)
{
return string.Empty;
}
else
{
return "error creating agency";
}
}
catch (ODataException oEx)
{
string s = oEx.Message;
throw;
}
catch (Exception ex)
{
string s = ex.Message;
throw;
}
}
private Entity CreateAccount(AgentTransmission agt)
{
account = new Entity();
account.Attributes.Add("LogicalName", "something");
account.Attributes.Add("name", agt.AgencyName);
account.Attributes.Add("telephone1", agt.BusinessPhone.Replace("(","").Replace(")", "").Replace("-", ""));
account.Attributes.Add("address1_line1", agt.MailingStreet1);
account.Attributes.Add("address1_city", agt.MailingCity);
account.Attributes.Add("address1_postalcode", agt.MailingZip);
account.Attributes.Add("neu_address1stateprovince", 1); //1 for Mailing
account.Attributes.Add("neu_channelid", LookupChannelId(agt.Channel));
account.Attributes.Add("neu_appointementstatus", "279660000");
account.Attributes.Add("customertypecode", LookupCustomerCode(agt.RelationshipType));
account.Attributes.Add("neu_taxid", UnobfuscateRef(agt.ReferenceNumber));
return account;
}
}
Set the name of the CRM entity on the LogicalName property of the Entity object rather than adding it to the attribute collection
account = new Entity("your_entity_name");
or
account = new Entity();
account.LogicalName = "your_entity_name";
Related
After reading about SOLID code in a book and in an online article, I wanted to refactor an existing class so that it can be 'SOLID'-compatible.
But I think I got lost, especially with the dependency injection: when I wanted to instantiate an object of the class, I needed to 'inject' the all the dependencies, but the dependencies themselves have dependencies.. this is where I started getting lost.
The Idea is like this: I want to create a class (In my case, a simple Amazon S3 wrapper class) to di simple upload & get URL actions.
How can I correctly use interfaces and dependency injection? what went wrong?
How should the class look like?
here is my code:
public interface IConfigurationProvider
{
string GetConfigurationValue(String configurationKey);
}
public interface ILogger
{
void WriteLog(String message);
}
public interface IAWSClientProvider
{
AmazonS3Client GetAmazonS3Client();
}
public interface IAWSBucketManager
{
string GetDefaultBucketName();
}
public class AWSBucketManager : IAWSBucketManager
{
ILogger logger;
IConfigurationProvider configurationProvider;
public AWSBucketManager(ILogger Logger, IConfigurationProvider ConfigurationProvider)
{
logger = Logger;
configurationProvider = ConfigurationProvider;
}
public string GetDefaultBucketName()
{
string bucketName = string.Empty;
try
{
bucketName = configurationProvider.GetConfigurationValue("Amazon_S3_ExportAds_BucketName");
}
catch (Exception ex)
{
logger.WriteLog(String.Format("getBucketName : Unable to get bucket name from configuration.\r\n{0}", ex));
}
return bucketName;
}
}
public class AWSClientProvider : IAWSClientProvider
{
IConfigurationProvider configurationProvider;
IAWSBucketManager awsBucketManager;
ILogger logger;
private string awsS3BucketName;
private Dictionary<string, RegionEndpoint> regionEndpoints;
public AWSClientProvider(IConfigurationProvider ConfigurationProvider, IAWSBucketManager BucketManager, ILogger Logger)
{
logger = Logger;
configurationProvider = ConfigurationProvider;
awsBucketManager = BucketManager;
}
private RegionEndpoint getAWSRegion()
{
RegionEndpoint regionEndpoint = null;
// Init endpoints dictionary
try
{
IEnumerable<RegionEndpoint> regions = RegionEndpoint.EnumerableAllRegions;
regionEndpoints = regions.ToDictionary(r => r.SystemName, r => r);
}
catch (Exception Ex)
{
logger.WriteLog(String.Format("getAWSRegion() - Failed to get region list from AWS.\r\n{0}", Ex));
throw;
}
// Get configuration value
try
{
string Config = configurationProvider.GetConfigurationValue("Amazon_S3_Region");
if (String.IsNullOrEmpty(Config))
{
throw new Exception("getAWSRegion() : Amazon_S3_Region must not be null or empty string.");
}
regionEndpoint = regionEndpoints[Config];
}
catch (Exception Ex)
{
logger.WriteLog(String.Format("getAWSRegion() : Unable to get region settings from configuration.\r\n{0}", Ex));
throw Ex;
}
return regionEndpoint;
}
private AWSCredentials getAWSCredentials()
{
string accessKey, secretKey;
BasicAWSCredentials awsCredentials;
try
{
accessKey = configurationProvider.GetConfigurationValue("Amazon_S3_AccessKey");
secretKey = configurationProvider.GetConfigurationValue("Amazon_S3_SecretKey");
}
catch (Exception Ex)
{
logger.WriteLog(String.Format("getAWSCredentials() - Unable to get access key and secrey key values from configuration.\r\n", Ex.Message));
throw;
}
try
{
awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
}
catch (Exception Ex)
{
logger.WriteLog(String.Format("getAWSCredentials() - Unable to create basic AWS credentials object.\r\n{0}", Ex.Message));
awsCredentials = null;
throw;
}
return awsCredentials;
}
public AmazonS3Client GetAmazonS3Client()
{
AmazonS3Client client = null;
RegionEndpoint region = getAWSRegion();
AWSCredentials credentials = getAWSCredentials();
awsS3BucketName = awsBucketManager.GetDefaultBucketName();
if (credentials != null)
{
client = new AmazonS3Client(credentials, region);
}
return client;
}
}
public class AWSS3Actions
{
IConfigurationProvider configurationProvider; // decoupling getting configuration
ILogger logger; // decoupling logger
IAWSClientProvider awsClientProvider;
private const int defaultExpirationDays = 14;
public AWSS3Actions(IConfigurationProvider ConfigurationProvider, ILogger Logger, IAWSClientProvider ClientProvider)
{
configurationProvider = ConfigurationProvider;
logger = Logger;
awsClientProvider = ClientProvider;
}
#region Private Mmethods
private string getFileUrl(string fileName, int expirationDaysPeriod, string awsS3BucketName)
{
GetPreSignedUrlRequest request = new GetPreSignedUrlRequest();
string URL = "";
DateTime dtBase = new DateTime();
dtBase = DateTime.Now;
dtBase = dtBase.AddDays(expirationDaysPeriod);
request.BucketName = awsS3BucketName;
request.Key = fileName;
request.Expires = dtBase;
try
{
URL = awsClientProvider.GetAmazonS3Client().GetPreSignedURL(request);
}
catch (AmazonS3Exception ex)
{
// log
logger.WriteLog(String.Format("getFileUrl() : Could not get presigned URL for the provided request.\r\n{0}", ex));
throw ex;
}
return URL;
}
private int getDefaultURLExpiration()
{
int expirationDays = 0;
try
{
// set the time span in days
int.TryParse(configurationProvider.GetConfigurationValue("getDefaultURLExpiration() : Amazon_S3_ExportAds_ExpirationDaysOfURL"), out expirationDays); // get from configuration util
}
catch
{
// in case of exception, set the min 14 days time space exiration
expirationDays = defaultExpirationDays;
}
return expirationDays;
}
private void validateUpload(string fileName, Stream fileStream)
{
if (fileName == null || fileName.Equals(string.Empty) || fileStream.Length < 1)
{
throw new Exception("fileName : File name must not be an empty string.");
}
if (fileStream == null)
{
throw new Exception("fileStream : Input memory stream (file stream) must not be null.");
}
}
#endregion
#region Public methods
public bool IsFileExists(string fileName, string awsS3BucketName)
{
bool fileExists = false;
try
{
S3FileInfo fileInfo = new S3FileInfo(awsClientProvider.GetAmazonS3Client(), awsS3BucketName, fileName);
fileExists = fileInfo.Exists;
}
catch (AmazonS3Exception Ex)
{
// log
logger.WriteLog(String.Format("isFileExists() : Could not determine if file (key) exists in S3 Bucket.\r\n", Ex.Message));
throw;
}
return fileExists;
}
public bool UploadObject(string fileName, Stream fileStream, string awsS3BucketName)
{
bool uploadResult = true;
// Validate input parameters
validateUpload(fileName, fileStream);
if (awsClientProvider.GetAmazonS3Client() != null)
{
try
{
PutObjectRequest request = new PutObjectRequest
{
BucketName = awsS3BucketName,
Key = fileName,
InputStream = fileStream
};
PutObjectResponse response = awsClientProvider.GetAmazonS3Client().PutObject(request);
if (response != null)
{
if (response.HttpStatusCode != System.Net.HttpStatusCode.OK)
{
var meta = response.ResponseMetadata.Metadata.Keys.
Select(k => k.ToString() + " : " + response.ResponseMetadata.Metadata[k]).
ToList().Aggregate((current, next) => current + "\r\n" + next);
// log error
logger.WriteLog(String.Format("Status Code: {0}\r\nETag : {1}\r\nResponse metadata : {1}",
(int)response.HttpStatusCode, response.ETag, meta));
// set the return value
uploadResult = false;
}
}
}
catch (AmazonS3Exception ex)
{
uploadResult = false;
if (ex.ErrorCode != null && (ex.ErrorCode.Equals("InvalidAccessKeyId") || ex.ErrorCode.Equals("InvalidSecurity")))
{
// LOG
logger.WriteLog(String.Format("UploadObject() : invalied credentials"));
throw ex;
}
else
{
// LOG
logger.WriteLog(String.Format("UploadObject() : Error occurred. Message:'{0}' when writing an object", ex.Message));
throw ex;
}
}
}
else
{
throw new Exception("UploadObject() : Could not start object upload because Amazon client is null.");
}
return uploadResult;
}
public bool UploadObject(string subFolderInBucket, string FileName, Stream fileStream, string awsS3BucketName)
{
return UploadObject(subFolderInBucket + #"/" + FileName, fileStream, awsS3BucketName);
}
public string GetURL(string fileName, string bucket)
{
string url = string.Empty;
try
{
if (IsFileExists(fileName, bucket))
{
url = getFileUrl(fileName, getDefaultURLExpiration(), bucket);
}
}
catch (Exception Ex)
{
// log
logger.WriteLog(String.Format("getURL : Failed in isFileExists() method. \r\n{0}", Ex.Message));
}
return url;
}
#endregion
}
With your current class structure, the Composition Root might look like this:
var logger = new FileLogger("c:\\temp\\log.txt");
var configurationProvider = new ConfigurationProvider();
var actions = new AWSS3Actions(
configurationProvider,
logger,
new AWSClientProvider(
configurationProvider,
new AWSBucketManagerlogger(
logger,
configurationProvider),
logger));
The above example shows a hand-wired object graph (a.k.a. Pure DI). My advice is to start off by applying Pure DI and switch to a DI library (such as Simple Injector, Autofac or StructureMap) when building up object graphs by hand becomes cumbersome and maintenance heavy.
From perspective of Dependency Injection, what you're doing seems sane, although your code smells. Here are some references to look at:
Logging and the SOLID principles
How to design a logger abstraction
Side note: In general it's better to load configuration values up front (at application start-up), instead of reading it at runtime. Reading those values at runtime, causes these values to be read in delayed fashion, which prevents the application from failing fast, and it spreads the use of the configuration abstraction throughout the application. If possible, inject those primitive configuration values directly into the constructor of the type that requires that value.
I have a c# .NET app that receives TCP and UDP streams from other devices on the network.
When I run it as console app, the Windows Firewall prompts me: "Windows Firewall has blocked some features of this program" and it ask me to allow vshost32.exe to communicate on the network.
I agree and the app works fine.
However when I run the app as a service (I have a separate console and service wrappers) I get no such prompt and I can only get it to work if switch off the firewall.
Is this expected for services? ()
Also, I have read some code snippets that suggest you can manually add exceptions to Windows Firewall list. Is this just for console apps or will it work for services also?
Some my code that listens on the ports in case this is usefull...
//
// Setup UDP listening
//
if (protocol == "UDP")
{
m_udp = new UdpConn("RedwallReceiver UDP", m_local, new NetAddress());
m_udp.Receive(new VDataHandler(ReceiveData));
}
//
// Setup TCP listening
//
if (protocol == "TCP")
{
m_listener = new TcpListener(m_local);
m_listener.Start();
m_listener.BeginAcceptSocket(AcceptSocket, null);
}
Services execute under restricted environments and are allowed to have very little or no interaction with the UI. His answer covers all the reasoning and here is how to achieve the same.
I would recommend adding an additional project to your solution (let's call it Configurator) which can be launched as part of the installation process. As far as I remember, adding a rule to the firewall requires administrative privileges. Here are the steps:
Create the Configurator project as a Console or WinForms application. No UI is needed here.
Add an application manifest file to the Configurator project. right-click project, Add > New Item > Application Manifest File. Change the <requestedExecutionLevel> tag to read <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />.
Add the output of the Configurator project to your setup/deployment project.
Select the deployment project and navigate to the Custom Actions tab. Add a new custom action under the Commit node and make it point to the output of the Configurator project.
In the Configurator project, add a reference to NetFwTypeLib from COM references.
Add the code below to the Configurator project.
Modify the Main method of the Configurator project to return an int (0 for success, non-zero for failure) and use the following code. Note that I've pasted this from my project directly so you may need to fix some decleration errors, etc.
private static int Main (string [] args)
{
var application = new NetFwAuthorizedApplication()
{
Name = "MyService",
Enabled = true,
RemoteAddresses = "*",
Scope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL,
IpVersion = NET_FW_IP_VERSION_.NET_FW_IP_VERSION_ANY,
ProcessImageFileName = "ServiceAssemblyName.dll",
};
return (FirewallUtilities.AddApplication(application, out exception) ? 0 : -1);
}
namespace MySolution.Configurator.Firewall
{
using System;
using System.Linq;
using NetFwTypeLib;
public sealed class NetFwAuthorizedApplication:
INetFwAuthorizedApplication
{
public string Name { get; set; }
public bool Enabled { get; set; }
public NET_FW_SCOPE_ Scope { get; set; }
public string RemoteAddresses { get; set; }
public string ProcessImageFileName { get; set; }
public NET_FW_IP_VERSION_ IpVersion { get; set; }
public NetFwAuthorizedApplication ()
{
this.Name = "";
this.Enabled = false;
this.RemoteAddresses = "";
this.ProcessImageFileName = "";
this.Scope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL;
this.IpVersion = NET_FW_IP_VERSION_.NET_FW_IP_VERSION_ANY;
}
public NetFwAuthorizedApplication (string name, bool enabled, string remoteAddresses, NET_FW_SCOPE_ scope, NET_FW_IP_VERSION_ ipVersion, string processImageFileName)
{
this.Name = name;
this.Scope = scope;
this.Enabled = enabled;
this.IpVersion = ipVersion;
this.RemoteAddresses = remoteAddresses;
this.ProcessImageFileName = processImageFileName;
}
public static NetFwAuthorizedApplication FromINetFwAuthorizedApplication (INetFwAuthorizedApplication application)
{
return (new NetFwAuthorizedApplication(application.Name, application.Enabled, application.RemoteAddresses, application.Scope, application.IpVersion, application.ProcessImageFileName));
}
}
}
namespace MySolution.Configurator.Firewall
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using NetFwTypeLib;
public static class FirewallUtilities
{
public static bool GetApplication (string processImageFileName, out INetFwAuthorizedApplication application, out Exception exception)
{
var result = false;
var comObjects = new Stack<object>();
exception = null;
application = null;
if (processImageFileName == null) { throw (new ArgumentNullException("processImageFileName")); }
if (processImageFileName.Trim().Length == 0) { throw (new ArgumentException("The argument [processImageFileName] cannot be empty.", "processImageFileName")); }
try
{
var type = Type.GetTypeFromProgID("HNetCfg.FwMgr", true);
try
{
var manager = (INetFwMgr) Activator.CreateInstance(type);
comObjects.Push(manager);
try
{
var policy = manager.LocalPolicy;
comObjects.Push(policy);
var profile = policy.CurrentProfile;
comObjects.Push(profile);
var applications = profile.AuthorizedApplications;
comObjects.Push(applications);
foreach (INetFwAuthorizedApplication app in applications)
{
comObjects.Push(app);
if (string.Compare(app.ProcessImageFileName, processImageFileName, true, CultureInfo.InvariantCulture) == 0)
{
result = true;
application = NetFwAuthorizedApplication.FromINetFwAuthorizedApplication(app);
break;
}
}
if (!result) { throw (new Exception("The requested application was not found.")); }
}
catch (Exception e)
{
exception = e;
}
}
catch (Exception e)
{
exception = e;
}
finally
{
while (comObjects.Count > 0)
{
ComUtilities.ReleaseComObject(comObjects.Pop());
}
}
}
catch (Exception e)
{
exception = e;
}
finally
{
}
return (result);
}
public static bool AddApplication (INetFwAuthorizedApplication application, out Exception exception)
{
var result = false;
var comObjects = new Stack<object>();
exception = null;
if (application == null) { throw (new ArgumentNullException("application")); }
try
{
var type = Type.GetTypeFromProgID("HNetCfg.FwMgr", true);
try
{
var manager = (INetFwMgr) Activator.CreateInstance(type);
comObjects.Push(manager);
try
{
var policy = manager.LocalPolicy;
comObjects.Push(policy);
var profile = policy.CurrentProfile;
comObjects.Push(profile);
var applications = profile.AuthorizedApplications;
comObjects.Push(applications);
applications.Add(application);
result = true;
}
catch (Exception e)
{
exception = e;
}
}
catch (Exception e)
{
exception = e;
}
finally
{
while (comObjects.Count > 0)
{
ComUtilities.ReleaseComObject(comObjects.Pop());
}
}
}
catch (Exception e)
{
exception = e;
}
finally
{
}
return (result);
}
public static bool RemoveApplication (string processImageFileName, out Exception exception)
{
var result = false;
var comObjects = new Stack<object>();
exception = null;
if (processImageFileName == null) { throw (new ArgumentNullException("processImageFileName")); }
if (processImageFileName.Trim().Length == 0) { throw (new ArgumentException("The argument [processImageFileName] cannot be empty.", "processImageFileName")); }
try
{
var type = Type.GetTypeFromProgID("HNetCfg.FwMgr", true);
try
{
var manager = (INetFwMgr) Activator.CreateInstance(type);
comObjects.Push(manager);
try
{
var policy = manager.LocalPolicy;
comObjects.Push(policy);
var profile = policy.CurrentProfile;
comObjects.Push(profile);
var applications = profile.AuthorizedApplications;
comObjects.Push(applications);
applications.Remove(processImageFileName);
result = true;
}
catch (Exception e)
{
exception = e;
}
}
catch (Exception e)
{
exception = e;
}
finally
{
while (comObjects.Count > 0)
{
ComUtilities.ReleaseComObject(comObjects.Pop());
}
}
}
catch (Exception e)
{
exception = e;
}
finally
{
}
return (result);
}
}
}
I have a method that is a search for Branches. the parameter is Branch Code and it should return the details of the branch
public bool SearchBranch()
{
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DBReader"].ConnectionString))
{
using (SqlCommand com = new SqlCommand("Reader.usp_SearchBranch", con))
{
com.CommandType = CommandType.StoredProcedure;
com.Parameters.Add("#BranchCode", SqlDbType.Int).Value = this.BranchCode;
con.Open();
SqlDataReader dr = com.ExecuteReader();
if (dr.Read())
{
this.BranchName = dr.GetValue(0).ToString();
this.AreaCode = dr.GetValue(1).ToString();
this.RegionCode = dr.GetValue(2).ToString();
this.CompanyCode = dr.GetValue(3).ToString();
this.CompanyName = dr.GetValue(4).ToString();
return true;
}
else
{
return false;
}
}
}
}
Here is my code in my Web Method in my Web Service (I dont know if this is correct)
[WebMethod(Description = "Search Affected User from Database in Access Request")]
public bool SearchBranchAccessRequest(AccessRequest accessrequest)
{
return accessrequest.SearchBranch();
}
And this is how I access/call the web method in my web page
protected void SearchBranchButton_Click(object sender, EventArgs e)
{
try
{
accessrequest.BranchCode = Convert.ToInt32(BranchCodeTextBox.Text);
iTicketWebService.SearchBranchAccessRequest(accessrequest);
if (iTicketWebService.SearchBranchAccessRequest(accessrequest) == true)
{
BranchNameLabel.Text = accessrequest.BranchName;
AreaLabel.Text = accessrequest.AreaCode;
RegionLabel.Text = accessrequest.RegionCode;
CompanyCodeLabel.Text = accessrequest.CompanyCode;
CompanyLabel.Text = accessrequest.CompanyName;
BranchEmailLabel.Text = accessrequest.BranchCode + "#pjlhuillier.com";
}
else
{
this.ClientScript.RegisterClientScriptBlock(this.GetType(), "clientScript", "<script type=\"text/javascript\">alert('Record not found. Please try again');</script>");
}
}
catch (Exception)
{
this.ClientScript.RegisterClientScriptBlock(this.GetType(), "clientScript", "<script type=\"text/javascript\">alert('Wrong Input. Please try again');</script>");
}
}
Help! it doesnt return Branch Name,Area Code,Region Code,Company Code and Company name?
change your web method as below
public AccessRequest SearchBranchAccessRequest(AccessRequest accessrequest)
{
return accessrequest.SearchBranch(accessrequest);
}
and you need to change SearchBranch() method as well
public accessrequest SearchBranch(AccessRequest accessrequest)
{
if(you found record in database)
{
// update accessrequest here
}else
{
accessrequest =null;
}
// finally return the object
return accessrequest;
}
when you call this web service
AccessRequest request = iTicketWebService.SearchBranchAccessRequest(accessrequest);
if(request!=null)
{
BranchNameLabel.Text = request.BranchName;
}
since your method signature change with above implementation, in case of null object return you can consider it as false case as your current implementation and if object return from the service you can consider it as true case.
If you need return true false from the service method and also need to have the updated object then you can have custom class to return both, like below
public class SearchBrancResponse
{
public bool SearchStatus { get; set; }
public AccessRequest AccessReq { get; set; }
}
you can then return above from the service method. from client side you have both Boolean value and the AccessRequest
This is my query where I'm returning an IEnumerable<CreditCardTransaction> to iterate through.
public partial class CreditCardTransaction
{
public static IEnumerable<CreditCardTransaction> GetUnprocessedTransactions()
{
try
{
using (var context = new SuburbanEntities())
{
return from trans in context.CreditCardTransactions
where trans.IsPublished == false
select trans;
}
}
catch (Exception ex)
{
Logging.Log("An error occurred.", "GetUnprocessedTransactions",Apps.ServicesConfig, ex);
return null;
}
}
}
This is where I am modifying those transactions once I have processed them:
public void ProcessFile()
{
try
{
_client = new TruckServiceClient();
_globalSetting = new GlobalSetting();
var unprocesstransactions = CreditCardTransaction.GetUnprocessedTransactions();
foreach (var creditCardTransaction in unprocesstransactions)
{
creditCardTransaction.IsPublished = ProcessTransaction(creditCardTransaction);
}
}
catch (Exception ex)
{
Logging.Log("An error occurred.", "ProcessCreditCardTransactions.ProcessFile", Apps.RemoteServices, ex);
}
}
I am modifying the transactions here:
creditCardTransaction.IsPublished = ProcessTransaction(creditCardTransaction);
But once I have saved them, can I update the entity directly or do I need to create another method where I pass this information back in?
The problem you don't have access to the context. Here you have some examples how to do:
https://github.com/geersch/EntityFrameworkObjectContext
If you're developing Asp.Net app, you'll have some drawbacks illustreted in this article:
http://dotnetslackers.com/articles/ado_net/Managing-Entity-Framework-ObjectContext-lifespan-and-scope-in-n-layered-ASP-NET-applications.aspx#managing-objectcontext-instantiation
Following up from this question:
designing application classes
What is wrong (from a design point of view) with this class:
I'm trying to refactor this class and it's abstract base class (Logon) and the fact it's actually horrible design. I wrote it myself (pretty much when I was a newbie). I'm finding it hard to refactor and want some input on it?
class NewUserLogon : Logon, ILogonNewUser, IDisposable
{
#region Member Variables
System.Windows.Forms.Form _frm = new MainWindow();
SQLDatabase.SQLDynamicDatabase sql;
SQLDatabase.DatabaseLogin dblogin;
LogonData lgndata;
System.Security.SecureString securepassword;
PasswordEncrypt.Collections.CreatedItems items;
LogonEventArgs e = new LogonEventArgs();
#endregion
#region Constructors
// for DI
public NewUserLogon(PasswordEncrypt.Collections.CreatedItems items) : base (items)
{
this.items = items;
}
#endregion
#region Public Methods
public new void Dispose()
{
}
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);
}
#endregion
#region Protected Methods
protected override void Login(string username, string password) // IS INSECURE!!! ONLY USE HASHES
{
base.Login(username, password);
if (_user is NewUserLogon) // new user
{
sql = new PasswordEncrypt.SQLDatabase.SQLDynamicDatabase();
dblogin = new SQLDatabase.DatabaseLogin();
lgndata = base._logondata;
securepassword = new System.Security.SecureString();
// Set Object for eventhandler
items.SetDatabaseLogin = dblogin;
items.SetSQLDynamicDatabase = sql; // recreates L
items.Items = items;
string generatedusername;
// write new logondata to registry
if (this.WriteToRegistry(lgndata.HahsedUserName, lgndata.HashedPsw))
{
try
{
// Generate DB Password...
dblogin.GenerateDBPassword();
// get generated password into securestring
securepassword = dblogin.Password;
//generate database username
generatedusername = dblogin.GenerateDBUserName(username);
if (generatedusername == "Already Exists")
{
throw new Exception("Username Already Exists");
}
//create SQL Server database
try
{
sql.CreateSQLDatabase(dblogin, username);
}
catch (Exception ex)
{
//System.Windows.Forms.MessageBox.Show(ex.Message);
e.ErrorMessage = ex.Message;
e.Success = false;
OnError(this, e);
}
}
catch (Exception exc)
{
e.Success = false;
e.ErrorMessage = exc.Message;
OnError(this, e);
}
OnNewUserLoggedIn(this, e); // tell UI class to start loading...
}
else
{
System.Windows.Forms.MessageBox.Show("Unable to write to Registry!", "Registry Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);
}
}
else if (_user is ExistingUserLogon) // exising user
{
bool? compare = base._regRead;
lgndata = base._logondata;
if (compare == true)
{
//Tell GUI to quit the 'busydialog' thread
OnMessage(this, e);
LogonFrm frm = LogonFrm.LogonFormInstance;
// tell user he already exists and just needs to login
// ask if user wants to logon straight away
System.Windows.Forms.DialogResult dlgres;
dlgres = System.Windows.Forms.MessageBox.Show("Your login already exists, do you wan to login now?", "Login Exists", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
if (dlgres == System.Windows.Forms.DialogResult.Yes)
{
ExistingUserLogon existinguser = new ExistingUserLogon(compare, lgndata);
existinguser.Error += new ErrorStatus(frm._newuser_Error);
existinguser.loginname = username;
existinguser.LoginNewUser();
///TELL GUI THAT USER LOGIN SUCCEEDED, THROUGH EVENT
e.Success = true;
OnNewUserLoggedIn(this, e);
}
else
{
e.Success = false;
e.ErrorMessage = "Failed";
OnError(this, e);
}
}
}
}
#endregion
}
Your class tries to do too many things. Try to separate different responsibilities into separate classes (eg database access and UI stuff).
And why are you instantiating a new Form at the beginning of your class and don't seem to use it further on?
Your protected Login is way too long.
Security should be a cross cutting concern, not a base class. I don't know if you have aspect oriented programming techniques available to you, but extending a base class with security built into it seems like an abuse of inheritance to me.