C# trim within the get; set; - c#

I am total MVC newbie coming from 10 years of webforms. Here is the code I have inherited:
namespace sample.Models
{
public class Pages
{
public int PageID { get; set; }
public string FolderName { get; set; }
}
}
How can I apply a trim function to the "set" portion of this code? Right now it is allowing spaces at the end of foldername and I need to prevent that.
Okay I have incorporated the suggestions however the spaces are still getting saved.
Here are the UI/ vs Database. The UI is trimming properly but the full value with spaces is stored in the table:

You need a backing field:
public class Pages
{
public int PageID { get; set; }
private string _folderName;
public string FolderName
{
get { return _folderName; }
set { _folderName = value.Trim(); }
}
}
In the setter method we use the Trim string's method, which
Removes all leading and trailing white-space characters from the current String object.
For further info regarding this method, please have a look here.

What about this solution:
public class Pages
{
private string _folderName;
public int PageID { get; set; }
public string FolderName
{
get { return _folderName; }
set { _folderName = value?.Trim() ?? string.Empty; }
}
}

You may consider writing a custom extension method to call Trim only if the value of your string is not null:
public static class CustomExtensions
{
public static string TrimIfNotNull(this string value)
{
if (value != null)
{
value = value.Trim();
}
return value;
}
}
And then in your Pages class, something like
private string _folderName;
public string FolderName
{
get { return _folderName.TrimIfNotNull(); }
set { _folderName = value.TrimIfNotNull(); }
}
If you're using C#6, as mentioned by Jacob Krall, you can use the null conditional operator directly and not worry about the extension method:
public string FolderName
{
get { return _folderName; }
set { _folderName = value?.Trim(); }
}

The shorthand syntax for properties is only for when you want to provide a thin layer of abstraction on top of a field. If you want to manipulate the field within the getter or setter, you need to specify the backing field on your own.
namespace sample.Models
{
public class Pages
{
public int PageID { get; set; }
private string folderName;
public string FolderName
{
get { return folderName; }
set { folderName = value.Trim(); }
}
}
}

public class Pages
{
public int PageId { get; set; }
// you need a backing field then you can customize the set and get code
private string folderName;
public string FolderName
{
get { return this.folderName; }
// if the fileName can be set to null you'll want to use ?. or you'll get
// a null reference exception
set { this.folderName = value?.Trim(); }
}
}

See the code below.
//You can filter the entry before saving it into the database.
//About the null issue. You can use this.
if(String.IsNullOrEmpty(txtusername.Text))
{
throw new Exception("Cannot be blank!");
}
//You can filter the entry before saving it into the database
txtpageid.Text = book.PageID.Trim();
txtfoldername.Text = book.FolderName.Trim();

Related

XML Deserialization and string format

I have an XML like this:
"<ArrayOfClsLog xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
<ClsLog>
<Subject>sth</Subject>
<Value>123456</Value>
<Comment>val</Comment>
</ClsLog>
</ArrayOfClsLog>"
and with this code I desterilize it:
var tmpSerializer = new XmlSerializer(typeof(ObservableCollection<ClsLog>));
tmpResult = tmpSerializer.Deserialize(tmpReader) as ObservableCollection<ClsLog>;
here is my ClsLog:
public class ClsLog
{
public string Subject { get; set; }
public string Value {get; set;}
public string Comment { get; set; }
}
Everything is fine except:
Big Problem
I want the content of value which can be a number like 123456 converts into 123,456
So I've changed Clslog to :
public class ClsLog
{
public string Subject { get; set; }
public string Value {
get
{
return decimal.Parse(Value.ToString()).ToString("N2", System.Globalization.CultureInfo.InvariantCulture);
}
set
{ }
}
public string Comment { get; set; }
}
But nothing changed, also I've tried to change tmpResult with LINQ:
tmpResult=tmpResult.ToList().ForEach(i => i.Value =
decimal.Parse( i.Value.ToString()).ToString("N2", System.Globalization.CultureInfo.InvariantCulture));
So bad exception happened and turned out I can't change it manually.
Question
How I can fix it? (make value from 123456 to 123.456)
You are declaring this property wrong.
public string Value //why a string why not a decimal?
{
get
{
// you have an infinite recursion here
return decimal.Parse(Value.ToString()).ToString("N2", System.Globalization.CultureInfo.InvariantCulture);
}
set { } // the setter is empty anyway so youcan't set it.
}
Instead try this
private decimal _value; // internal field
public decimal Value
{
get
{
return _value; // return internal field
}
set
{
_value = value / 1000; // set the internal field to the value / 1000
}
}

Assigning data to attributes and static attributes directly in c#

I have a method as follows which gets data and stores them to specific variables. I also have two static variables that preserves their value if a condition is met. My question is how can I store this data in attributes in a specific class ?
Like for example, I have a class called UserDetails with attributes :
UserDetails class
public class UserDetails {
public static string RateCountry { get; set; }
public static string RateWeek { get; set; }
public int Start { get; set; }
public int Length { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
Second Class
For now, its working like this. But I want to enhance it by making use of objects.
public static string RateCountry { get; private set; }
public static string RateWeek { get; private set; }
public ActionResult ShowList()
{
int start = Convert.ToInt32(Request["start"]);
int length = Convert.ToInt32(Request["length"]);
string name = Request["search[value]"];
string address = Request[("columns[3][search][value]")];
string rateType = Request[("columns[7][search][value]")];
if (string.IsNullOrEmpty(rateType)) // if null, reset the static variables to null
{
RateCountry = "";
RateWeek = "";
}
else
{
if (CheckDate(rateType)) // if contains date, assign to RateWeek
{
RateWeek = rateType;
}
else
{
RateCountry = rateType; // else if contains a string word, assing to ratecountry
}
}
var items = AssignDetails(start, length, name, address, RateWeek, RateCountry);
return items;
}
Then instead of passing several parameters like start, length, name etc. in the method AssignDetails, I can pass an object of the UserDetails class directly taking into consideration the static variables.
Can someone please help ?
Note: In C#, they are called properties not attributes. Attributes are a totally different thing.
What you want to do is straight forward:
Firstly, you need to change your method so it accepts your class UserDetails as an argument:
public void AssignDetails(UserDetails userDetails)
{
// Use userDetails here to do whatever you want
}
Secondly, when you call the above method, you need to pass the argument to it. You can create an instance of UserDetails and pass it to the AssignDetails method:
var userDetails = new UserDetails
{
Start = start,
Length = length,
Name = name
Address = address
}
I am not sure why RateWeek, and RateCountry properties are static in your class, but to set those you can do them as below (Please note it is using the class and not the instance of the class):
UserDetails.RateWeek = RateWeek;
You could make use of the instance's properties as an indirection to the class' static properties, although all this thing is really ugly in terms of design.
public class UserDetails
{
public static string PersistedRateCountry { get; set; }
public static string PersistedRateWeek { get; set; }
public static string RateCountry
{
get { return string.IsNullOrEmpty(rateType) ? "" : PersistedRateCountry; }
set { PersistedRateCountry = value; }
}
public static string RateWeek
{
get { return string.IsNullOrEmpty(rateType) ? "" : PersistedRateWeek; }
set { PersistedRateWeek= value; }
}
public static string RateWeek { get; set; }
public int Start { get; set; }
public int Length { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
I strongly suggest you to move these static properties out to another class, which would be responsible for persisting them.
E.g. try to separate your Data Object (which just holds data) from your Business Object (which contains business logic, and is constructed by receiving a Data Object as parameter). Put all that crazy persistence logic in the Business Object, and use the Business Object everywhere in your code (instead of using the Data Object).
Keep your classes short and clean. If you are coding a lot in the same class, it's probably because you got a bad object-oriented design.

Triggering get and set for properties using attribute

I need to build an attribute that will override the getter and the setter of an property. To be more clear, here is how it works today and how it should work using the attribute (the result should be the same).
Old version:
public class A
{
private Handle _handle;
public String StringProp
{
get {
return _handle.GetProperty(PropId.StringProp);
}
set {
_handle.SetProperty(PropId.StringProp, value);
}
}
public int IntProp
{
get {
return _handle.GetProperty(PropId.IntProp);
}
set {
_handle.SetProperty(PropId.IntProp, value);
}
}
}
New version:
public class A
{
private Handle _handle;
[HandleProperty(PropId.StringProp)]
public String StringProp { get; set; }
[HandleProperty(PropId.IntProp)]
public int IntProp { get; set; }
}
The attribute HandleProperty should known to link the getter and setter to _handle.GetProperty and _handle.SetProperty.
I created two enums and some of the fields in one enum were mapped to another enums fields using attributes. I think you can do something like this...
[AttributeUsage(AttributeTargets.Field)]
public sealed class MapsToAttribute : Attribute
{
private string Text;
public string MapsToText
{
get
{
return Text;
}
}
public MapsToAttribute(string mapsToText)
{
Text = mapsToText;
}
public override string ToString()
{
return Text;
}
}

if property1 is empty, then use property2

public string FirstPersonName
{Get; set; }
public string LocationName
{Get; set; }
public PropertyEvidenceBL()
{
if (FirstPersonName==string.empty)
{
//grab the LocationName in its place. How do I write this.
return LocationName; //does not work
}
query GetPropertyReport contains all person location info.
business class is PropertyEvidenceBL that has all objects/properties
It looks like you have a return statement in the constructor from your posted code. Why?
Try something like this.
Also note you most likely want string.IsNullOrEmpty or string.IsNullOrWhiteSpace as your test. FirstPersonName in your case is likely null and not empty. Two very different things.
public string FirstPersonName { get; set; }
public string LocationName { get; set; }
public string PersonOrLocationName {
get {
return !string.IsNullOrEmpty(FirstPersonName) ? FirstPersonName : LocationName;
}
}
// From your post this looks like the class constructor...
public PropertyEvidenceBL
{
// Do something with the name...
string name = PersonOrLocationName;
}
If you're curious about the ? : syntax, it's shorthand for this:
if(!string.IsNullOrEmpty(FirstPersonName) {
return FirstPersonName
}
else {
return LocationName;
}
What you could do is separate out your logic checking if the FirstPersonName is empty. Obviously with more code in there handle the return from the CheckFirstName method (not sure what you are doing with it).
public PropertyEvidenceBL()
{
CheckFirstName();
}
private string CheckFirstName()
{
if (FirstPersonName == string.empty)
{
return LocationName;
}
else
{
return FirstPersonName
}
}

Setting only a setter property

I have an object model that has a property like this:
public class SomeModel
{
public string SomeString { get; set; }
public void DoSomeWork()
{
....
}
}
I want the DoSomeWork function to execute automatically after the SomeString property changes. I tried this but it's not working:
public string SomeString { get; set { DoSomeWork(); } }
What's the correct syntax?
Use a private field instead, like this ...
public class SomeModel
{
private string someString = "";
public string SomeString {
get { return this.someString; }
set {
this.someString = value;
this.DoSomeWork();
}
}
public void DoSomeWork()
{
....
}
}
You can't do this with automatic properties - you'll have to create a "manual" property backed by a field.
private string _someString;
public string SomeString
{
get { return _someString; }
set
{
_someString = value;
DoSomeWork();
}
}
If you really can't deal with this boilerplate (say you'd have to do this hundreds of times), consider using an AOP framework like PostSharp to implement this on your behalf - you'd just need to declare an automatic property and an attribute to get the binary rewriter to implement the desired scheme.
This will work...
private string _someString;
public string SomeString { get { return _someString; } set { _someString = value; DoSomeWork(); } }
private string _someString;
public string SomeString
{
get
{
return _someString;
}
set
{
DoSomeWork();
_someString = value;
}
}
C# team has introduced the auto-implement properties in C# 3.0. with the logic of minimizing the model making which is backed by an anonymous field created by compiler. this one is used when you don't need to implement any additional logic on a property of an object class. so it just followed as.
public string Name{ get; set;}// auto-implemented property. no additional logic.
if we want to add some logic as you want to add one function. we must be writing a manual property backed by a private field as like below.
private string _Name;
public string Name
{
get {return _Name;}
set {
_Name=value;
DoSomething(); //Additional logic implemented.
}
}

Categories

Resources