How to Clear/Remove an ActiveDirectory property with ExtensionSet - c#

I'm using the Principal Extensions for a User in AD to access properties not normally retrieved by the UserPrincipal. My custom properties are defined like such:
[DirectoryProperty("facsimileTelephoneNumber")]
public string FaxNumber
{
get
{
if (ExtensionGet("facsimileTelephoneNumber").Length != 1)
return null;
return (string)ExtensionGet("facsimileTelephoneNumber")[0];
}
set
{
ExtensionSet("facsimileTelephoneNumber", value);
}
}
How do you clear the property with ExtensionSet? If I input null or empty string, I will almost always get this error message: "The attribute syntax specified to the directory service is invalid.". It sounds like you should clear the property but I'm unsure how this works with ExtensionSet.

The problem was I was not sending back an array, I was only sending back the value, not an array:
[DirectoryProperty("facsimileTelephoneNumber")]
public string FaxNumber
{
get
{
if (ExtensionGet("facsimileTelephoneNumber").Length != 1)
return null;
return (string)ExtensionGet("facsimileTelephoneNumber")[0];
}
set
{
ExtensionSet("facsimileTelephoneNumber", string.IsNullOrEmpty(value) ? new string[1] {null} : new string[1] {value});
}
}

Related

In asp.net core, are empty string converted to NULL?

Assuming I have a form, and the value of "" is selected when the form is sent from the view to the controller to the action method, will asp.net core convert the empty string to a NULL value?
If I do not make the Boolean property nullable for the [required] attribute, it gives me this error: The value '' is invalid.
Does this mean that: "" is evaluated as NULL, the Boolean property does not allow NULL, asp.net core returns a error saying that you can not pass a empty string to the Model property because it is not nullable because asp.net core converts the empty string to a NULL?
MVC model binding does support binding an empty string as either a null or empty string, depending on metadata.
You can control that behaviour per field with attributes;
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Property { get; set; }
Or override that behaviour globally by implementing a custom IDisplayMetadataProvider.
public class DisplayProvider : IDisplayMetadataProvider
{
public void CreateDisplayMetadata(DisplayMetadataProviderContext context)
{
if (context.Key.ModelType == typeof(string))
context.DisplayMetadata.ConvertEmptyStringToNull = false;
}
}
// in .AddMvc(o => ...) / AddControllers(o => ...) / or an IConfigure<MvcOptions> service
[MvcOptions].ModelMetadataDetailsProviders.Add(new DisplayProvider());
Or convert values in any way you like by providing your own IModelBinder / IModelBinderProvider.
public class StringBindProvider : IModelBinderProvider
{
private StringBinder stringBinder = new StringBinder();
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context.Metadata.ModelType == typeof(string))
return stringBinder;
return null;
}
}
public class StringBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (value != ValueProviderResult.None)
{
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, value);
var str = value.FirstValue?.Trim();
if (bindingContext.ModelMetadata.ConvertEmptyStringToNull && string.IsNullOrWhiteSpace(str))
str = null;
bindingContext.Result = ModelBindingResult.Success(str);
}
return Task.CompletedTask;
}
}
// see above
[MvcOptions].ModelBinderProviders.Insert(0, new StringBindProvider());
The first thing you need to understand is that the Options field here is the type of bool(not string).
The only content it can receive is true or false or null, whether you enter an empty string or a string other than true or false, it will recognized as null.
The attribute of Reuqired indicates that the Options field cannot be null,because Options is a bool type, so after you enter an empty string, the empty string is converted to a null value, and due to the restriction of the reuqired attribute, it cannot be null, so it will remind you invalid.
If you want to allow Options to receive null values, you only need to remove the reuqired attribute.
In the premise of the Required attribute limitation, I did a code test, you can refer to:
No they are not - the message says "The value '' is invalid." which is how an empty string looks like.
you need to set value for boolean if you don't want to set required field. You need to send false if it is empty.

Umbraco 7 if File Upload is empty

I'm using Umbraco 7 with a File Upload. I would like to check IF there is or isn't a file uploaded.
If there isn't a file uploaded, I recieve the following error: Object reference not set to an instance of an object.
I have removed some code to make it easier to read through, but below is my surfacecontroller:
using System.Web.Mvc;
using Umbraco.Web.Mvc;
using Umbraco.Web;
namespace Sp34k.Controllers
{
public class GalleryItem
{
public string projectFile { get; set; }
}
public class PortfolioSurfaceController : SurfaceController
{
// GET: PortfolioSurface
public ActionResult GetCategoryDetails(int id)
{
GalleryItem gItem = new GalleryItem();
var node = Umbraco.TypedContent(id);
string file = node["uploadProjectFiles"].ToString();
if (string.IsNullOrWhiteSpace(file))
{
gItem.projectFile = node["uploadProjectFiles"].ToString();
}
return Json(gItem, JsonRequestBehavior.AllowGet);
}
}
}
I assume the problem is on this line:
string file = node["uploadProjectFiles"].ToString();
You may get a null as response to this from node with that key and you cannot call ToString() on it.
There is also another issue: if the string is null or whitespace you assign it to gItem.projectFile. I would assume you only want to assign it if it is not null or whitespace.
If the object in node is definitely a string or null, you can fix the code easily:
string file = node["uploadProjectFiles"] as string;
if (!string.IsNullOrWhiteSpace(file))
{
gItem.projectFile = file;
}
The as string means "if the object is a string assign it as such, or if it isn't return null." This way you either get a string (might still be empty/whitespace) or null with the type string and you can check it.
The node key which you are accessing is null probably, you need to check for null on it as well:
string file = node["uploadProjectFiles"] !=null ? node["uploadProjectFiles"].ToString() : String.Empty;
and then next use file variable:
if (string.IsNullOrWhiteSpace(file))
{
gItem.projectFile = file;
}

Array field parsed from JSON is empty

I don't understand why this happens. I'm consuming REST service via WCF. In case of error the service sends this kind of message body (I see in Fiddler):
{"Errors":["Some text"],"StatusCode":500}
I have created a class for this, and getting it via Message.GetBody(). StatusCode is filled, but Errors are always empty (not null, but empty). I have tried String[], List of String, also tried initialized backing field. What is wrong here?
Here is the class:
[DataContract(Name="root", Namespace="")]
public class ErrorResult
{
[DataMember]
public string[] Errors { get; set; }
[DataMember]
public int StatusCode { get; set; }
public override String ToString()
{
return String.Join(Environment.NewLine, Errors);
}
}
Here is the parsing:
public void AfterReceiveReply(ref Message reply, object correlationState)
{
var resp = reply.Properties[HttpResponseMessageProperty.Name] as HttpResponseMessageProperty;
if (resp != null && resp.StatusCode != HttpStatusCode.OK)
{
String message = null;
try
{
ErrorResult res = reply.GetBody<ErrorResult>();
if (res != null)
{
message = res.ToString();
}
}
catch { }
if (!String.IsNullOrEmpty(message))
{
throw new Exception(message);
}
}
}
I'm using [DataContract(Name="root", Namespace="")] because I was getting error "expecting element ErrorResult with namespace 'bla-bla-bla' but got element 'root' with namespace ''".
UPDATE. I have noticed the same problem with another entity, the one which was service result type. It contained 2 integer fields, and on return they were 0s, even though I could see in Fiddler and in Message.ToString() values there. I have fixed this by adding Name="..." to DataMember attributes, even though those names are the same as property names, except casing (JSON camel vs C# pascal). I was sure that C# parsing is case insensitive! Ok, but adding names to ErrorResult in subject still didn't fix the problem with array.
UPDATE 2. Ok, after not finding any solution, I did a workaround in an "ugly way". At least this started working at once.
XmlDocument doc = new XmlDocument();
doc.LoadXml(reply.ToString());
String message = String.Join(Environment.NewLine,
doc.SelectNodes("/root/Errors/item").OfType<XmlNode>().Select(n => n.InnerText));
I have also tried XMlSerialzer with Message.GetReaderAtBodyContents(), but got "error in XML" and gave it up.
Here is explained what to do to make List work. I usually use arrays (eg: string[] not Array class) to avoid problems or additional configuration and cast on client side.

UPDATE operation - Operation is not valid due to the current state of the object

I have two tables that are linked by a foreign key reference, let's call them RX and program.
I have this method that tries to change the program id in the RX table, which is an FKR to the program id field in the program table. Whenever I try to do this, I get an
"Operation is not valid due to the current state of the object"
Which gets fired on:
System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException();
What am I doing wrong here?
The offending code snippet and the database field definition are below. Code:
public void ChangeProgram(int programId, DbDataContext dc)
{
//var programId = ddlPrograms.SelectedValue.ToInteger(0);
if (programId > 0)
{
var referral = PrescriptionManager.GetReferral(dc, _view.RxID);
if (referral != null && referral.AspnRx.ProgramID != programId)
{
try
{
referral.ProgramID = dc.PROGRAMs.Single(p => p.ProgramID == programId).ToString().ToInteger(1);
}
catch (ForeignKeyReferenceAlreadyHasValueException exception)
{
_view.ChangeProgramSuccess = false;
}
Database field definition:
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ProgramID", DbType="Int")]
public System.Nullable<int> ProgramID
{
get
{
return this._ProgramID;
}
set
{
if ((this._ProgramID != value))
{
if (this._PROGRAM.HasLoadedOrAssignedValue)
{
throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException();
}
this.OnProgramIDChanging(value);
this.SendPropertyChanging();
this._ProgramID = value;
this.SendPropertyChanged("ProgramID");
this.OnProgramIDChanged();
}
}
}
Its a LinqToSql thing, what you are doing would work fine in EF and possibly other ORMs. You have to set the property that represents the object to the a new object rather than just updating the property that maps to the foreign key field in the database.
Presuming you have a property called Program then do this instead:
referral.Program = dc.PROGRAMs.Single(p => p.ProgramID == programId);
Not really related but .ToString().ToInteger(1), looks a bit dubious, looks like you are taking an integer, converting it into a string then back to an integer.

how to force WebAPI in MVC4 to render null strings as empty in json result

How to render null string properties as empty strings in ASP.NET MVC4 Web API v.1 in json result?
WebAPI renders them as
"myproperty": null
how to render this as
"myproperty": ""
controller is
public class Customer {
public string myproperty { get; set; }
}
public class CustomersController : ApiController
{
public HttpResponseMessage Get()
{
var cust = new Customer();
return Request.CreateResponse(HttpStatusCode.OK,
new { customers = cust.ToArray() });
}
}
object are nested and contain lot of string properties. Setting them all to empty strings in constructor seems ugly. API caller needs empty strings or 0 for decimals, it does not like null constant in any value.
you can decorate your properties like this :
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
[DefaultValue("")]
public string myproperty{ get; set; }
Note that you can set the default value handling to populate in a global config like this:
GlobalConfiguration
.Configuration
.Formatters
.JsonFormatter
.SerializerSettings
.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Populate;
So, you don't need to decorate it to every property. You will only need to use the DefaultValue.
public class Customer {
private string _myproperty = String.Empty;
public string myproperty
{
get { return _myproperty; };
set { _myproperty = value ?? String.Empty; }
}
}
i give little overhead but solve my problem
DataTable dt = (new tst()).Gettable();
string s = string.Empty;
s = Newtonsoft.Json.JsonConvert.SerializeObject(dt);
s= s.Replace("null", "\"\"");
Object obj = Newtonsoft.Json.JsonConvert.DeserializeObject(s);
return Ok(obj);
As default web api works like this...
you don't need to change

Categories