I have a querystring with a number of optional values eg.
/filter?location=scotland&minprice=100&maxprice=500
I have a filter method with a number of optional arguments
public List<result> Filter(
bool isVisible = false,
string location = null,
int? minPrice = null,
int? maxPrice = null,
)
I would like to use the querystring values as arguments on the filter method, but I can't think of a good way to do this.
The best way I can come up with is to use ?: conditions for each argument
var results = Filter(
(Request.QueryString["isvisible"] != null ? Request.QueryString["isvisible"] == "true" : false)
and so on...
but using this method, if a particular querystring value hasn't been set, I have to pass in a default value, but I don't want to pass in a default, I want defaults to be set from within the filter method.
Is there a way to do this? Or is there a better way to achieve the same thing?
Sounds like you just need to map the defaults.
There are actually two "interfaces" here: the interface from the caller to the Filter() method and the interface from the Filter() method to the data source. They don't have to have the same defaults.
public List<Whatever> Filter(string criteria1 = null, string criteria2 = null)
{
criteria1 = criteria1 ?? SYSTEM_DEFAULT_FOR_CRITERIA1;
criteria2 = criteria2 ?? SYSTEM_DEFAULT_FOR_CRITERIA2;
return _dataSource.GetData(criteria1, criteria2);
}
Related
I have a problem with all my controller endpoints, whenever I use sort and filter as query parameter in a way similar to this example:
[Microsoft.AspNetCore.Mvc.HttpGet,
Microsoft.AspNetCore.Mvc.Route("{tenantId}/archive/retrievals", Name = "getRetrievalList")]
public System.Threading.Tasks.Task<RetrievalListResult> GetRetrievalList([Microsoft.AspNetCore.Mvc.FromQuery] int? limit = null, [Microsoft.AspNetCore.Mvc.FromQuery] int? offset = null, [Microsoft.AspNetCore.Mvc.FromQuery] System.Collections.Generic.IEnumerable<string> sort = null, [Microsoft.AspNetCore.Mvc.FromQuery] System.Collections.Generic.IDictionary<string, string> filter = null)
{
throw new NotImplementedException();
}
It works perfectly fine with these calls:
{{baseUrl}}/:tenantId/archive/retrievals?filter[fields]=Text 01
{{baseUrl}}/:tenantId/archive/retrievals?sort=name&filter[fields]=Text 01
But when I only use sort…
{{baseUrl}}/:tenantId/archive/retrievals?sort=name
...then suddenly both sort and filter variables are filled, creating a false filter parameter.
Any solutions for that?
P.S. using only filter=id results in none of the variables being filled which is as I expect.
For Dictionary targets, model binding looks for matches to parameter_name or property_name. If no match is found, it looks for one of the supported formats without the prefix.
In other words, "sort=name" matches the format of the supported target parameter Dictionary<string, string> named filter.
Therefore, it will also be automatically bound to the filter.
You can specify the prefix to solve the problem.
public IEnumerable<WeatherForecast> Get(
[FromQuery] int? limit = null,
[FromQuery] int? offset = null,
[FromQuery] IEnumerable<string> sort = null,
[FromQuery][Bind(Prefix = "filter")]IDictionary<string, string> filter = null
)
I have a method where I have several optional boolean parameters, different properties of an object will be given a value based on which parameters are true.
Here is the method for context:
public static AutoPatientLookup InitializeTestPatientInfo(bool SSN = false, bool PatientNumber = false, bool Gender = false)
{
AutoPatientLookup TestAPIParameters = new AutoPatientLookup();
TestAPIParameters.FirstName = "First";
TestAPIParameters.LastName = "Last";
TestAPIParameters.DOB = "4/9/1953";
TestAPIParameters.PracticeID = 11071;
if (SSN)
{
TestAPIParameters.SSN = 000010281;
}
if (PatientNumber)
{
TestAPIParameters.PatientNumber = 458;
}
if (Gender)
{
TestAPIParameters.Gender = "F";
}
return TestAPIParameters;
}
However, sometimes I want the second or third boolean parameter to be true but I'm unable to designate that as the parameter I want to switch without explicitly stating true or false for the preceding parameters.
This if I want to initialize an AutoPatientLookup object that has a value for its gender property, I would have to call it like this:
InitializeTestPatientInfo(false,false,true);
I tried something along the lines of
InitializeTestPatientInfo(Gender = true);
and
InitializeTestPatientInfo(bool Gender = true);
but nothing seems to work. Is there a correct syntax for accomplishing for what I'm attempting? Even though the initialization syntax isn't very inconvenient when there are only three boolean parameters this could be more applicable if there are dozens.
The syntax you want to use is:
InitializeTestPatientInfo(Gender: true);
Try
InitializeTestPatientInfo(Gender: true);
You can name your parameter that you are assigning:
Do this instead
InitializeTestPatientInfo(Gender: true);
string mid = Request.QueryString["ID"];
if ( db.Movies.Where(i=>i.ID==mid))
{
repMovie.DataSource = db.Movies.Find().ToString();
repMovie.DataBind();
}
Try adding .Any() to return a boolean in your if statement.
Any() returns true if any results are returned by an enumerable object.
if ( db.Movies.Where(i=>i.ID==mid).Any())
{
//...
}
First, db.Movies.Where(i=>i.ID==mid) isn't a boolean. Why are you testing if it's true or false?
Second, repMovie.DataSource = db.Movies.Find().ToString(); has no condition on it. How will that return the right thing? Why don't you do this instead:
(Assuming there's going to be a maximum of one match, ever):
var matchingMovie = db.Movies.FirstOrDefault(i => i.ID == movieId);
if (matchingMovie !== null) {
// you found it in one operation and can work with it now
}
I recommend against variable names like mid. What's that? Anyone else who sees it, or even yourself in a few months, will have no idea and will have to do extra scanning work to figure out its meaning. Use movieId instead.
And for that matter, why are you getting the movieId directly from the querystring yourself? Your MVC action methods should do this for you:
public ActionResult Index(int ID) {
// Lookie! you've automatically gotten the ID from the querystring, and
// you also know it's a non-null integer. If it were null or a non-integer,
// it wouldn't match this route and the client would get a 404, unless you
// had another route to handle those.
}
Alternate ways
int numMid = Convert.ToInt32(mid);
if ( db.Movies.Where(i=>i.ID==numMid).Count()>0)
{
//...
}
or
int numMid = Convert.ToInt32(mid);
if (db.Movies.Any(i=>i.ID==numMid))
{
//...
}
I am retrieving user information from a database using a simple query.
select * from dbo.[User] u where u.Email = #email
I then try to get the value of a column, called IsConfirmed (which is represented as a bit type column in the database) and convert it to bool.
bool isConfirmed = int.Parse(sqlDataReader["IsConfirmed"].ToString()) == 1;
I then get an FormatException error, stating that "Input string was not in a correct format.".
I saw a similar question with an answer providing this code:
bool isConfirmed = sqlDataReader.GetBoolean(0);
But this won't work with my case, because I don't know the index of the IsConfirmed column and I don't want to know it. I want to use the column name.
The value returned from the data reader indexer property is of type object but can be cast to the data type it has been stored as.
Try this:
bool isConfirmed = (bool)sqlDataReader["IsConfirmed"]
If you want to use the column name you can use
bool isConfirmed = sqlDataReader.GetBoolean(sqlDataReader.GetOrdinal("IsConfirmed"));
Your code should work if you don't have any null value in your column IsConfirmed.
Usually these bit columns have a NOT NULL property and/or a default value of 0, but it could happen to have a null value and, in this case, your code will fail with the error mentioned.
You could fix it in this way (You will need the column position for this check however)
int colPos = sqlDataReader.GetOrdinal("IsConfirmed");
bool isConfirmed = sqlDataReader.IsDBNull(colPos) ? false : sqlDataReader.GetBoolean(colPos));
If you really dislike to have a call to find the Column Position you could create an extension method that allow you to hide the call
public static class ReaderExtensions
{
public static bool IsDBNull(this SqlDataReader reader, string colName)
{
int colPos = reader.GetOrdinal(colName);
return reader.IsDBNull(colPos);
}
}
and call it with
bool isConfirmed = int.Parse((sqlDataReader.IsDBNull("IsConfirmed")
? "0" : sqlDataReader["IsConfirmed"].ToString())) == 1;
Try this: Convert.ToBoolean(reader["Columnname"]) or with Ordinal for example: Convert.ToBoolean((3))
For nullable boolean (if you may have null boolean values), you can try
bool? isConfirmed = sqlDataReader["IsConfirmed"] as bool?;
just I want to ask is it possible to Call function as ToUpper or ToLower() as string for example f.Name.Replace(" ", "_").ToLower()".ToLower()" or "ToUpper" for example if user select convert file name to ToLower() from dropdown list.it will take the value 'ToLower' and added to in of the function and executed the function call
Well, not cleanly. You could use reflection to find the method but you'd have to know the exact type that the function will be applied to since you won't get sophisticated binding like you do at compile-time. Plus you'll be limited to one method signature (in this case, no input parameters and returns a string).
To support any string function with that signature you could use:
string val = f.Name.Replace(" ", "_").ToLower();
string strCommand = "ToUpper";
MethodInfo theMethod = typeof(string).GetMethod(strCommand,new Type[] {});
string result = (string)(theMethod.Invoke(val,null));
But a simple switch seems cleaner and safer here.
The conditional operator (?:) would probably be a better option here
var fileName = f.Name.Replace(" ", "_");
fileName = ddl.SelectedValue == "ToLower" ? fileName.ToLower() : fileName.ToUpper();
Using Reflection for something as trivial as this is pretty unnecessary.
If you know the methods you want to call before, you can register them in a dictionary (key = name of the function or something user friendly, value = function that performs the conversion):
var dict = new Dictionary<string, Func<string, string>>();
dict.Add("Lowercase", x => x.ToLower());
dict.Add("Uppercase", x => x.ToUpper());
You can bind the drop down list to the dictionary (text = Key, value = Value) and perform the conversion as follows (ddl is the name of the DropDownList):
var f = (Func<string, string>)ddl.SelectedValue;
var convStr = f(inputStr);
You can create a defined dictionary of functions, which you can access by name of the action. You will get rid of any conditional statements and of all reflection. Example is given below:
var actions = new Dictionary<string, Func<string, string>>()
{
//keys may have other, human-readable values
{"ToLower", s => s.ToLower()},
{"ToUpper", s => s.ToUpper()}
};
//you will receive this from drop down list, it's the name of the action
var userSelectedOption = "ToUpper";
//string that you want to process
var myString = "some other user input";
//selecting appropriate action and passing myString to it
var transformedString = actions[userSelectedOption](myString);
//prints "SOME OTHER USER INPUT"
Console.WriteLine(transformedString);
Using reflection, you can call a methods using a string:
String ToLower = "ToLower";
String SometString = "This Is My String";
Type stringType = typeof(String);
// Get the overload of ToLower that takes no parameters
MethodInfo method = stringType.GetMethod(ToLower, System.Type.EmptyTypes);
// Invoke the method with no parameters
String newString = (String)method.Invoke(SometString, null);
MessageBox.Show(newString);
If I have understood your question correctly, you want to call a method based on a string.
You can use reflection, which is a topic in and of itself, but to get you started you can do something like:
MethodInfo chosenMethod = typeof(string).GetMethod(methodName, Types.EmptyTypes);
chosenMethod.Invoke(stringToModify, new object[]{});
But if it is a very limited set of functions you want to expose, you should just do a switch statement over the user input:
switch(methodName)
{
case "ToLower":
stringToModify.ToLower();
break;
...
You can use a simple switch statement:
switch (value) // Assuming value is of type SomeEnum
{
case SomeEnum.ToLower:
return f.ToLower()
case SomeEnum.ToUpper:
return f.ToUpper();
default:
//Do the Default
break;
}
This is how you parse what you get from the UI:
public static T ParseEnum<T>( string value )
{
return (T) Enum.Parse( typeof( T ), value, true );
}
Perhaps you might need to avoid limitations is sort of a Runtime intepreter of C#, like eval() function in JavaScript, which is not easily nor trivial to implement, but there is a good library out there called C# Eval ( http://csharp-eval.com/Download.php ) that uses Reflection internally of course. It is heavier but more effective for this, or even for much more complex escenarios.
You might use it in this way for example:
class Person
{
public string Name;
public string Process(string expression)
{
return CsEval.Eval(this, expression);
}
}
And then might call it:
var f = new Person();
f.Name = "John";
f.Name = f.Process("Name.Replace(" ", "_").ToLower()");
Of course this is just an example of how it evaluate what is in the string, as you can see you just need to pass a "context" where the expression is going to mean something, which in this case is the current class ("this").