ASP.Net MVC : Get query values with no key - asp.net-mvc

I have URL: http://site.com/page.aspx?update
how do I check if that update value is present?
HttpValueCollection treats that as an entity with null key. I have tried:
var noKeyValues = Request.QueryString.GetValues(null);
if (noKeyValues != null && noKeyValues.Any(v=>v==update)) ...
but it gives me a frowny line, because GetValues' argument is decorated with [NotNull].
so I end up doing:
var queryValuesWithNoKey =
Request.QueryString.AllKeys.Select((key, index) => new { key, value = Request.QueryString.GetValues(index) }).Where(
item => item.key == null).Select(item => item.value).SingleOrDefault();
if (queryValuesWithNoKey != null && queryValuesWithNoKey.Any(v => v.ToLower() == "update")) live = true;
not the most elegant workaround. Is there a better way to get key-less value from query string?

You can use
Request.QueryString[null]
to retrieve a comma separated list of keys with no values. For instance, if your url is:
http://mysite/?first&second
then the above will return
first,second
In your case, you could just do something like:
if(Request.QueryString[null] == "update")
{
// it's an update
}

if that's the only key you would use
Request.QueryString.ToString() to get the "update" value

I know I'm late to the party, but this a function that I use for this kind of task.
internal static bool HasQueryStringKey(HttpRequestBase request, string key)
{
// If there isn't a value, ASP will not recognize variable / key names.
string[] qsParts = request.QueryString.ToString().Split('&');
int qsLen = qsParts.Length;
for (int i = 0; i < qsLen; i++)
{
string[] bits = qsParts[i].Split('=');
if (bits[0].Equals(key, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
You may need to update it so that it is case sensitive, or uses different arguments depending on your purposes, but this has always worked well for me.

Related

breeze query where clause is not executed

I'm quite new to using breeze and at the moment stuck with something which seems very simple.
I have a API call which returns 4 locations. Then using breeze, I'm trying to filter it down using a where clause as follows:
function getLocations(clientId) {
var self = this;
return EntityQuery.from('GetLocations')
.withParameters({ clientId: clientId })
.where("activeStatus", "==", "0")
.expand('LocationType')
.using(self.manager)
.execute()
.then(querySucceeded, this._queryFailed);
function querySucceeded(data) {
if (data.results.length > 1) {
locations = data.results;
}
return locations;
}
}
Ideally, this should give me 0 rows, because in all 4 rows the 'activeStatus' is 1. However, it still shows me all 4 results. I tried with another filter for locationType, and it's the same result. The breeze side where clause does not get executed.
Update to answer the questions:
Following is how the API call in my controller looks like:
public object GetLocations(int clientId) {
}
As you see it only accepts the clientId as a parameter hence I use the with parameter clause. I was thinking that breeze will take care of the activeStatus where clause and I don't have to do the filter on that in the back-end. Is that wrong?
Can someone help with this?
The Breeze documentation indicates that the withParameters is usually used with non-.NET backends or servers which do not recognize oData URIs. Is it possible that the where clause is being ignored because of .withParameters? Can't you rewrite the where clause using the clientID filter?
function getLocations(clientId) {
var self = this;
var p1 = new breeze.Predicate("activeStatus","==","0");
var p2 = new breeze.Predicate("clientId","==",clientId);
var p = p1.and(p2)
return EntityQuery.from('GetLocations')
.where(p)
.expand('LocationType')
.using(self.manager)
.execute()
.then(querySucceeded, this._queryFailed);
function querySucceeded(data) {
if (data.results.length > 1) {
locations = data.results;
}
return locations;
}
}
I'd try this first. Or put the where clause in the withParameters statement, depending on your backend. If that doesn't work, then there might be other options.
Good Luck.
EDIT: An example that I use:
This is the API endpoint that I query against:
// GET: breeze/RST_ClientHistory/SeasonClients
[HttpGet]
[BreezeQueryable(MaxExpansionDepth = 10)]
public IQueryable<SeasonClient> SeasonClients()
{
return _contextProvider.Context.SeasonClients;
}
And here is an example of a query I use:
// qFilters is object. Values are arrays or strings, keys are id fields. SeasonClients might also be Clients
// Setup predicates
var p, p1;
// link up the predicates for passed data
for (var f in qFilters) {
var compareOp = Object.prototype.toString.call(qFilters[f]) === '[object Array]' ? 'in' : '==';
if (!qFilters[f] || (compareOp == 'in' && qFilters[f].length == 0)) continue;
fLC = f.toLowerCase();
if (fLC == "countryid") {
p1 = breeze.Predicate("District.Region.CountryId", compareOp, qFilters[f]);
} else if (fLC == "seasonid") {
p1 = breeze.Predicate("SeasonId", compareOp, qFilters[f]);
} else if (fLC == "districtid") {
p1 = breeze.Predicate("DistrictId", compareOp, qFilters[f]);
} else if (fLC == "siteid") {
p1 = breeze.Predicate("Group.Site.SiteId", compareOp, qFilters[f]);
} else if (fLC == "groupid") {
p1 = breeze.Predicate("GroupId", compareOp, qFilters[f]);
} else if (fLC == "clientid" || fLC == 'seasonclientid') {
p1 = breeze.Predicate("ClientId", compareOp, qFilters[f]);
}
// Setup predicates
if (p1) {
p = p ? p.and(p1) : p1;
}
}
// Requires [BreezeQueryable(MaxExpansionDepth = 10)] in controller
var qry = breeze.EntityQuery
.from("SeasonClients")
.expand("Client,Group.Site,Season,VSeasonClientCredit,District.Region.Country,Repayments.RepaymentType")
.orderBy("DistrictId,SeasonId,GroupId,ClientId");
// Add predicates to query, if any exist
if (p) qry = qry.where(p);
return qry;
That's longer than it needs to be, but I wanted to make sure a full working example is in here. You will notice that there is no reason to use .withParameters. As long as the Context is set up properly on the server, chaining predicates (where clauses) should work fine. In this case, we are creating where clauses with up to 10 ANDs filtering with strict equality or IN a collection, depending on what is passed in the qFilters Object.
I think you should probably get rid of the parameter in your backend controller, make the method parameterless, and include the clientId match as an additional predicate in your query.
This approach also makes your API endpoint much more flexible -- you can use it for a wide variety of queries, even if the ClientId has nothing to do with them.
Does this help? Let me know if you have any more questions?

Result of MAX()- method

I have table tb_Orders (it empty), which have fields^
- order_id (int) (primary key)
- order_date nchar(30)
In my application, when client make order, requests the function:
private int GetNewOrderId()
{
int ord_id = 0;
if (db.tb_Orders.Max(x => x.order_id) != null)
{
int ord = db.tb_Orders.Max(x => x.order_id);
ord_id = ord + 1;
}
else
{
ord_id = 1;
};
return ord_id;
}
which get the new order id (+1 to max order in table).
Operator "if" must, when the table is still empty, get id = 1;
But the result - error (when I try to get id).
ERROR TEXT: "Error converting cast a value type "Int32", as materialize value is null."
Try casting your order_id to a nullable integer when making the Max call:
private int GetNewOrderId()
{
int nextOrderId = db.tb_Orders.Max(x => (int?)x.order_id) ?? 1;
return nextOrderId;
}
You will also notice that in my example there's only a single SQL query to the database whereas you were making 2: one in the if statement and another one inside.
It seems your order_id is Nullable<int>. Use the Value property to get it's value, and you can also perform the query before if statement and don't execute the query twice:
var max = db.tb_Orders.Max(x => x.order_id);
if(max != null)
{
int ord = max.Value;
ord_id = ord + 1;
}

Cannot compare in linq

I am trying to get the result of the user logged in but receiving this error :
"Cannot compare elements of type 'System.Linq.IQueryable`1'. Only
primitive types, enumeration types and entity types are supported. "
Here is the query I'm applying in my index action:
var viewModel = new PointsViewModel();
viewModel.Point = db.Point.ToList();
viewModel.Redeem = db.Redeem.ToList();
TempData["UserPoints"] = null;
var usrname = (from a in db.Instructors
where a.Email == User.Identity.Name
select new { a.PersonID });
if (usrname.Count().Equals(0))
{
TempData["UserPoints"] = "You have not earn any points yet.";
return View();
}
viewModel.instructor = db.Instructors
.Where(i => i.PersonID.Equals(usrname))// if I directly insert id here then it works properly but I don't want direct inserts
.Single();
PopulateAssignedPointData(viewModel.instructor);
return View(viewModel);
Please help me with this please...I am unable to find any solution on google
It's because you're passing usrname as a parameter to another query. usrname is a query, not a value, so you need to retrieve a value from the query (in this case, by using First(), but you could just as easily use Single() if you like) before you can use it as a parameter in another query. I would recommend the following changes:
if (!usrname.Any())
{
TempData["UserPoints"] = "You have not earn any points yet.";
return View();
}
var personId = usrname.First();
viewModel.instructor = db.Instructors
.Where(i => i.PersonID.Equals(personId))
.Single();
I also changed usrname.Count().Equals(0) to !usrname.Any() as it is more idiomatic (it will use the exists keyword in SQL, rather than count)
Try to use this:
viewModel.instructor = db.Instructors
.Where(i => usrname.Any(u => u.PersonID == i.PersonID))
.Single();

How to cache aggregate column values on Doctrine_Record instance?

Lets say i have a record class that often gets queried with dyanmic colums that are MySQL aggregate values:
$results = Doctrine_Core::getTable('MyRecord')->creatQuery('m')
->select('m.*, AVG(m.rating) as avg_rating, SUM(m.id) as nb_related')
->innerJoin('m.AnotherRecords a')
->where('m.id = ?')
->fetchOne();
Now lets say i want a method on that record to check if the aggregate columns exist from when the record was queried, and if not then i want to go ahead an issue a separate query to get these values:
// this doesnt actually work because of filterSet and filterGet
// but its general idea
public function getAverageRating($wtihNbRelated = false)
{
if(!isset($this->avg_rating) || ($withNbRelated && !isset($this->nb_related))
{
$rating = $this->getTable()->getAverageRating($this, $withNbRelated);
$this->avg_rating = $rating['avg_rating'];
if($withNbRealted)
{
$this->nb_related = $rating['nb_related'];
}
}
return $withNbRelated
? array('avg_rating' => $this->avg_rating, 'nb_related' => $this->nb_related)
: array('avg_rating' => $this->avg_rating);
}
Is there an easy way (ie. not writing a custom hydrator) to do this?
Simple answer really. I forgot that Doctrine prefixes all its direct protected members with _. So, even though i initially tried manipulating the data member i was forgot the prefix giving me the same result as if i tried $this->avg_rating or its accessor method. The solution was:
public function getAverageRating($wtihNbRelated = false)
{
if(!isset($this->_data['avg_rating']) || ($withNbRelated && !isset($this->_data['nb_related']))
{
$rating = $this->getTable()->getAverageRating($this, $withNbRelated);
$this->_data['avg_rating'] = $rating['avg_rating'];
if($withNbRealted)
{
$this->_data['nb_related'] = $rating['nb_related'];
}
}
return $withNbRelated
? array('avg_rating' => $this->_data['avg_rating'], 'nb_related' => $this->_data['nb_related'])
: array('avg_rating' => $this->_data['avg_rating']);
}

Making Grails data-binding interpret empty String values ("") as zero (0)

This question is about altering how the Grails data-binding handles string-to-integer conversion.
Consider the following domain object:
class Foo {
String name
Integer price
}
Furthermore, assume that the domain object is populated from HTTP request parameters:
def foo = new Foo(params).save()
The save() method above will fail if params.price == "" (empty string). I'd like to change this behaviour globally so that an empty string is parsed as zero (0) when converting from a string to an integer in Grails data-binding. How do I achieve that?
added a filter see the setion 5.5.1 Events and Auto Timestamping in the grails documentation (http://grails.org/doc/1.1.x/index.html)
def beforeInsert = {
if (price == '') { price = 0}
}
Instead of changing the data binding why not just write your own setter? In the setter test to see if the string is empty, if it is set price to 0. If it isn't do a normal integer conversion.
try this constraint instead
static constraints = {
price(validator: {val, obj ->
if (val == '' || val == 0) {
obj.price = 0
return true
} else if (val < 1) {
return false;
}
})
}
import org.grails.databinding.BindUsing
class Foo {
String name
#BindUsing({ obj, source ->
source["price"] ?: 0
})
Integer price
}

Resources