MVC3 select with condition give strange behavior - asp.net-mvc-3

I'm trying to implement a result filter with MVC3 and face a problem like this:
public ActionResult Index(int? SubID)
{
var product = db.Product.Where(s => s.SubID == SubID).Include(t => t.SubCategory);
if (SubID.HasValue)
{
ViewBag.SubID = new SelectList(db.SubCategory, "SubID", "SubNameVN", SubID);
}
else
{
ViewBag.SubID = new SelectList(db.SubCategory, "SubID", "SubNameVN");
}
return View(product);
}
This one above works fine, but the following one always give me result of the whole table, despite what condition I put on it:
public ActionResult Index(int? SubID)
{
var product = db.Product.Include(t => t.SubCategory);
if (SubID.HasValue)
{
ViewBag.SubID = new SelectList(db.SubCategory, "SubID", "SubNameVN", SubID);
product.Where(s => s.SubID == SubID);
}
else
{
ViewBag.SubID = new SelectList(db.SubCategory, "SubID", "SubNameVN");
}
return View(product);
}
And even this one doesn't work too:
public ActionResult Index(int? SubID)
{
var product = from m in db.Product
select m;
if (SubID.HasValue)
{
ViewBag.SubID = new SelectList(db.SubCategory, "SubID", "SubNameVN", SubID);
product.Where(s => s.SubID == SubID);
}
else
{
ViewBag.SubID = new SelectList(db.SubCategory, "SubID", "SubNameVN");
}
product.Include(t => t.SubCategory);
return View(product);
}
So please tell me what is the difference between these 3 approaches, and please explain to me why #2 and #3 don't work?

product.Where(s => s.SubID == SubID);
...does not add a condition on product, it just creates an IEnumerable with the condition applied, and immediately throws it away. What you want is probably;
product = product.Where(s => s.SubID == SubID);

Related

When I run this method it hits the RedirectToAction but not the breakpoint i have placed above it

I have a class for a cart in a store and when the buy method gets run it skips the breakpoint and still hits the RedirectToAction at the bottom of the method. This is the code for the method
public ActionResult Buy(int productid /*string optionid*/)
{
Product productModel = new Product();
List<ProductOptionJoin> productOptionJoins = GetProductOptions();
var test = productOptionJoins.Where(x => x.ProductID == productid && x.OptionID.ToString() == "1" /*optionid*/).Select(x => new CartItem() { getProduct = x.GetProduct, getOption = x.GetOption });
var i = test;
if (Session["cart"] == null)
{
List<CartItem> cart = new List<CartItem>();
//cart.Add(new CartItem { getProduct = productModel.find(id), getOption = productModel.find(id), Quantity = 1 });
Session["cart"] = cart;
}
else
{
List<CartItem> cart = (List<CartItem>)Session["cart"];
int index = isExist(productid);
if (index != -1)
{
cart[index].Quantity++;
}
else
{
//cart.Add(new CartItem { getProduct = productModel.find(id), getOption = productModel.find(id), Quantity = productModel.find(id) });
}
Session["cart"] = cart;
}
return RedirectToAction("Index");
}
Any ideas?
You are only creating the session variable at the end, maybe put it above?
Product productModel = new Product();
List<ProductOptionJoin> productOptionJoins = GetProductOptions();
var test = productOptionJoins.Where(x => x.ProductID == productid && x.OptionID.ToString() == "1" /*optionid*/).Select(x => new CartItem() { getProduct = x.GetProduct, getOption = x.GetOption });
var i = test;
Session["cart"] = xyz;

Dynamic where clause with two entity

I need a filter between two entity.
Have two tables 1.User 2.Product
Product map with the User table.
I am going to create a dynamic where filter.
I need to find out all the users which have 'test' product.
Conditions: if userFilter count is 0 then I need all test product with the respected user.
If userFilter is there and productFilter is there then below code is working but if userFilter is not there and productFilter is there then it returning 0 row. How can I find the users which have test product? ?
Here is my Code.
public IHttpActionResult GetFilter()
{
var userFilters = new List<Filter>()
{
new Filter { PropertyName = "Username" ,
Operation = Op .Equals, Value = "Karan" },
};
var productfilter = new List<Filter>()
{
new Filter { PropertyName = "Name" ,
Operation = Op .Equals, Value = "Test product" }
};
Func<User, bool> deleg = x => true;
Func<Product, bool> delegProduct = x => true;
if (userFilters.Count > 0)
{
deleg = ExpressionBuilder.GetExpression<User>(userFilters).Compile();
}
if (productfilter.Count > 0)
{
delegProduct = ExpressionBuilder.GetExpression<Product>(productfilter).Compile();
}
var resultt = _localmarketEntities.Users.Where(deleg)
.Select(x => new
{
x.Id,
x.Username,
Product = x.Products.Where(delegProduct).Select(y => new
{
y.Id,
y.Name
}).ToList()
})
.ToList();
return Ok(resultt);
}
if i understand correct, you need all users that have test product when userFiler count is 0.
List<User> res;
var user = _localmarketEntities.Users.Where(deleg).ToList();
if (user.Count == 0) {
res = _localmarketEntities.Products.Where(delegProduct).Select(q => new User() {
Id = q.Id,
Username = q.Username,
Product = q
}).ToList();
}
else {
res = _localmarketEntities.Users.Where(deleg)
.Select(x => new
{
x.Id,
x.Username,
Product = x.Products.Where(delegProduct).Select(y => new
{
y.Id,
y.Name
}).ToList()
})
.ToList();
}

url.Action with MvcContrib generates invalid links

In our application we use MvcContrib for generating links with the exception of cross area links where Contrib seems to be not working properly (or we are doing something wrong). In services we have a function that generates a List< ZakladkaModel > which contains url and other properties used in generating tabstrib via custom html helper. That function takes as an argument an id of database object and UrlHelper to help in link creating.
m_service.GenerowanieZakladkiDlaKontrolera_ARCH_Akt(idAktu, new UrlHelper(this.ControllerContext.RequestContext));
Then in the GenerowanieZakladkiDlaKontrolera_ARCH_Akt we have something like this:
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "Akt", Url = "" });
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "Wzmianki", Url = url.Action<Usc.Presentation.Areas.FU_RAU.Controllers.ARCH.ARCH_WzmiankiController>(c => c.Index(idAktu)) });
if (tekstJednolity.StanTekstuJednolitego == "RB" || tekstJednolity.StanTekstuJednolitego == "SW")
{
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "t.j. aktu", Url = url.Action<Usc.Presentation.Areas.FU_RAU.Controllers.ARCH.ARCH_TekstJednolityController>(c => c.Edytuj(tekstJednolity.Id)) });
}
else
{
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "t.j. aktu", Url = url.Action<Usc.Presentation.Areas.FU_RAU.Controllers.ARCH.ARCH_TekstJednolityController>(c => c.Raport(tekstJednolity.Id)) });
}
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "Przypisek 1", Url = url.Action<Usc.Presentation.Areas.FU_RAU.Controllers.ARCH.Przypisek1Controller>(c => c.Index(idAktu)) });
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "Przypisek 2", Url = url.Action<Usc.Presentation.Areas.FU_RAU.Controllers.ARCH.Przypisek2Controller>(c => c.Index(idAktu)) });
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "Przypisek 3", Url = url.Action<Usc.Presentation.Areas.FU_RAU.Controllers.ARCH.Przypisek3Controller>(c => c.Edytuj(idAktu)) });
model.Add(new ZakladkaModel { Aktywnosc = true, NazwaZakladki = "Przypisek 4", Url = url.Action<Usc.Presentation.Areas.FU_RAU.Controllers.ARCH.Przypisek4Controller>(c => c.Edytuj(idAktu)) });
Now the problem is that on some co-workers computers it generates links to actions properly and on some it looks like it takes a ranedom area from our app and tries to make an invalid link. We could use a simple url.Action("action","controler") which works fine on all but we would prefer MvcContrib :). Does anyone have any idea why this occurs? Or can share an alternative?
It seems that LinkBuilder which is used under doesn't use GetVirtualPatchForArea at all which as I read is MVC bug. So i decided to make my own HtmlHelper which uses that method:
public static string ActionArea<TController>(this HtmlHelper urlHelper, Expression<Action<TController>> expression) where TController : Controller
{
RouteValueDictionary routeValues = GetRouteValuesFromExpression(expression);
VirtualPathData vpd = new UrlHelper(urlHelper.ViewContext.RequestContext).RouteCollection.GetVirtualPathForArea(urlHelper.ViewContext.RequestContext, routeValues);
return (vpd == null) ? null : vpd.VirtualPath;
}
public static string ActionArea<TController>(this UrlHelper urlHelper, Expression<Action<TController>> expression) where TController : Controller
{
RouteValueDictionary routeValues = GetRouteValuesFromExpression(expression);
VirtualPathData vpd = urlHelper.RouteCollection.GetVirtualPathForArea(urlHelper.RequestContext, routeValues);
return (vpd == null) ? null : vpd.VirtualPath;
}
public static RouteValueDictionary GetRouteValuesFromExpression<TController>(Expression<Action<TController>> action) where TController : Controller
{
if (action == null)
{
throw new ArgumentNullException("action");
}
MethodCallExpression call = action.Body as MethodCallExpression;
if (call == null)
{
throw new ArgumentException("Akcja nie może być pusta.", "action");
}
string controllerName = typeof(TController).Name;
if (!controllerName.EndsWith("Controller", StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException("Docelowa klasa nie jest kontrolerem.(Nie kończy się na 'Controller')", "action");
}
controllerName = controllerName.Substring(0, controllerName.Length - "Controller".Length);
if (controllerName.Length == 0)
{
throw new ArgumentException("Nie można przejść do kontrolera.", "action");
}
// TODO: How do we know that this method is even web callable?
// For now, we just let the call itself throw an exception.
string actionName = GetTargetActionName(call.Method);
var rvd = new RouteValueDictionary();
rvd.Add("Controller", controllerName);
rvd.Add("Action", actionName);
var namespaceNazwa = typeof(TController).Namespace;
if(namespaceNazwa.Contains("Areas."))
{
int index = namespaceNazwa.IndexOf('.',namespaceNazwa.IndexOf("Areas."));
string nazwaArea = namespaceNazwa.Substring(namespaceNazwa.IndexOf("Areas.") + 6, index - namespaceNazwa.IndexOf("Areas.") + 1);
if (!String.IsNullOrEmpty(nazwaArea))
{
rvd.Add("Area", nazwaArea);
}
}
//var typ = typeof(TController).GetCustomAttributes(typeof(ActionLinkAreaAttribute), true /* inherit */).FirstOrDefault();
/*ActionLinkAreaAttribute areaAttr = typ as ActionLinkAreaAttribute;
if (areaAttr != null)
{
string areaName = areaAttr.Area;
rvd.Add("Area", areaName);
}*/
AddParameterValuesFromExpressionToDictionary(rvd, call);
return rvd;
}
private static string GetTargetActionName(MethodInfo methodInfo)
{
string methodName = methodInfo.Name;
// do we know this not to be an action?
if (methodInfo.IsDefined(typeof(NonActionAttribute), true /* inherit */))
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture,
"Nie można wywoływać metod innych niż akcje.", methodName));
}
// has this been renamed?
ActionNameAttribute nameAttr = methodInfo.GetCustomAttributes(typeof(ActionNameAttribute), true /* inherit */).OfType<ActionNameAttribute>().FirstOrDefault();
if (nameAttr != null)
{
return nameAttr.Name;
}
// targeting an async action?
if (methodInfo.DeclaringType.IsSubclassOf(typeof(AsyncController)))
{
if (methodName.EndsWith("Async", StringComparison.OrdinalIgnoreCase))
{
return methodName.Substring(0, methodName.Length - "Async".Length);
}
if (methodName.EndsWith("Completed", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture,
"Nie można wywoływać kompletnych metod.", methodName));
}
}
// fallback
return methodName;
}
static void AddParameterValuesFromExpressionToDictionary(RouteValueDictionary rvd, MethodCallExpression call)
{
ParameterInfo[] parameters = call.Method.GetParameters();
if (parameters.Length > 0)
{
for (int i = 0; i < parameters.Length; i++)
{
Expression arg = call.Arguments[i];
object value = null;
ConstantExpression ce = arg as ConstantExpression;
if (ce != null)
{
// If argument is a constant expression, just get the value
value = ce.Value;
}
else
{
value = CachedExpressionCompiler.Evaluate(arg);
}
rvd.Add(parameters[i].Name, value);
}
}
}
Hope this helps people with similiar problems. Some of the code above i got from mvc2-rtm-sources modified to my needs http://aspnet.codeplex.com/releases/view/41742

MVC 3 - How to know if query returns 0 rows

Probably pretty easy, but I can't get it sorted out. I want to redirect the user to an error page if the requested id doesn't exist in the database. My code:
public ActionResult Details(int id)
{
DetailsAdViewModel DAVM = new DetailsAdViewModel();
DAVM.Ad = db.Ads.Include("Images").Where(a => a.AdId == id).First();
DAVM.FirstImage = db.Images.Where(a => a.AdId == id).OrderBy(a => a.ImageId).Take(1);
// make sure the ad isn't deleted or that it really exists
if (DAVM.Ad == null)
{
return RedirectToAction("ShowError", "Error", new { errorCode = "adDeleted" });
}
return View(DAVM);
}
This doesn't work, and there is an server error if I enter a false id.
Use .FirstOrDefault() instead of .First(). This will return null if not record is found instead of throwing an exception:
DAVM.Ad = db.Ads.Include("Images").FirstOrDefault(a => a.AdId == id);
Now you can check if DAVM.Ad is null:
if (DAVM.Ad == null)
{
return RedirectToAction("ShowError", "Error", new { errorCode = "adDeleted" });
}
Found a solution:
public ActionResult Details(int id)
{
if (db.Ads.Any(a => a.AdId == id))
{
DetailsAdViewModel DAVM = new DetailsAdViewModel();
DAVM.Ad = db.Ads.Include("Images").Where(a => a.AdId == id).First();
DAVM.FirstImage = db.Images.Where(a => a.AdId == id).OrderBy(a => a.ImageId).Take(1);
return View(DAVM);
}
else
{
return RedirectToAction("ShowError", "Error", new { errorCode = "adDeleted" });
}
}

string array to be separated with comma

I had a string array which I want it to be returned in view separated by comma.
#Html.DisplayFor(m => name.studentName) <span>, </span>}
I'm using this way but the last string will ended with a comma also. Wondering how to avoid this?
I assume that you have a collection of students on your model each possessing a studentName property that you want to display:
public IEnumerable<Student> Students { get; set; }
And inside your view you are looping through this collection and displaying each student name individually.
Now instead of looping you could do the following:
#Html.Raw(
string.Join(
"<span>,<span>",
Model.Students.Select(x => Html.Encode(x.studentName))
)
)
or even better, externalize this logic into a reusable custom HTML helper:
public static class HtmlExtensions
{
public static IHtmlString FormatStudentNames(this HtmlHelper htmlHelper, IEnumerable<Student> students)
{
return new HtmlString(
string.Join(
"<span>,<span>",
students.Select(x => Html.Encode(x.studentName))
)
);
}
}
and then inside your view simply call this helper:
#Html.FormatStudentNames(Model.Students)
You no longer need to write any foreach or whatever loops you are writing.
Try
#string.Join(",", name.studentName);
And have a look at string.Join on MSDN.
$(".category").change(function () {
var value = $(this).val();
loadSubCategory(value)
});
function loadSubCategory(parentID) {
var $el = $("#SubCats");
$el.prop("disabled", true);
$el.empty();
$.ajax({
cache: false,
url: "/Category/loadSubCategory?id=" + parentID,
success: function (data) {
if (data != '' && data != null) {
if (data != 'error') {
var sch = JSON.parse(data);
if (sch.length > 0) {
$el.prop("disabled", false);
for (i = 0; i < sch.length; i++) {
$el.append($("<option></option>")
.attr("value", sch[i].ID).text(sch[i].Description));
}
}
}
}
}
});
}
public ActionResult loadSubCategory(string id)
{
string list = "";
try
{
list = Newtonsoft.Json.JsonConvert.SerializeObject(menu.SubCategory(id));
}
catch (Exception ex)
{
}
return Content(list);
}
public List<CategoryModel> SubCategory(string parentID){
List<CategoryModel> listCategory= new List<CategoryModel>();
string[] yourValues = parentID.Split(',');
foreach (var item in yourValues)
{
var Category = UowObj.CategoryRepository.Get(filter: c => c.ParentId.ToString() == item && c.IsActive == true).ToList();
if (Category != null)
{
var category= new CategoryModel();
foreach (var itemq in Category)
{
category.ID = itemq.ID;
category.Description = itemq.Description;
}
listCategory.Add(merchant);
}
}

Resources