I have 2 entities Orders and Items with OrdersController and ItemsController.
In my Orders Index View I have a webgrid
grid.Column(columnName: "OrderNo", header: "Order No.", canSort: true),
grid.Column(columnName: "OrderDate", header: "Order Date", canSort: true),
grid.Column(" ", " ", format: #Items)
In ItemsController I've added to Index a parameter :
public ActionResult Index(string id = "0")
{
var orderq = from a in db.items
where a.OrderNo== id
select a;
return View(orderq.ToList()); // ex : orderq.Count = 2
}...
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
} // Object reference not set to an instance of an object
But I get Object reference not set to an instance of an object.
Q : What do I have to to open the items view from my orders ?
Do I have to clear my context and declare it again ?
Order.cshtml
grid.Column(" ", " ", format: #Items)));
ItemsController.cs
public ActionResult Index(string id = "0")
{
var itemsqry = db.items.Where(a=>a.OrderNo == id);
return View(itemsqry .ToList());
}
Related
Hi everyone I wanna get url like {Controller}/{action}/{postid}-{address}
but routUrl returns null please help me to solve it.(I'm newbie in MVC)
my route config is
routes.MapRoute(
name: "Post",
url: "Posts/Show/{postid}-{address}",
defaults: new { controller = "Posts", action = "Index", postid = "", address = "" }
);
and index.cshtml
#item.PostTitle
the url that generate is
http://localhost:59066/Posts/Show/1-Post-with-Featured-Image
but in PostsController
public ActionResult Show(string add)
{ return View();}
"string add" is null !
I wouldn't change the Routes...
try this...
#item.PostTitle
This will send PostId and Address as parameters, so you can get them in the controller like:
public ActionResult AwesomeThings(int PostId, String Address)
{
var foo = PostId;
var bar = Address;
return View(model);
}
No changes in routing,
Index.cshtml:
#item.PostTitle
Controller:
public ActionResult Show(string postid, string address)
{ return View();}
I changed the route to
routes.MapRoute("Post", "post/{postid}-{address}", new { controller = "Posts", action = "Show" ,postid="",address=""}, namespaces);
and added a route with same controller and action
routes.MapRoute("PostAddress", "post/{IdAndAdd}", new { controller = "Posts", action = "Show" }, namespaces);
routes.MapRoute("Post", "post/{postid}-{address}", new { controller = "Posts", action = "Show" ,postid="",address=""}, namespaces);
then action received "idAndAdd" correctly
public ActionResult Show(string idAndAdd)
{
var parts = SeperateAddress(idAndAdd);
if (parts == null)
return HttpNotFound();
var post = db.Posts.Find(parts.Item1);
if (post == null)
return HttpNotFound();
if (!post.Address.Equals(parts.Item2, StringComparison.CurrentCultureIgnoreCase))
return RedirectToRoutePermanent("Post", new { postid = parts.Item1, address = post.Address });
return View(post);
}
and it's worked .
I have a pagination problem. I have a Product model, it has a string ProductCategory attribute. One page can take 4 products, whenever it exceeds 4, it points out page 2. The problem is that when I click "Car" category and click page 2, it takes every product, rather than taking only "Car" .
I got the book from the book, ASP.NET MVC 4, published by apress.
Here is my ProductListViewModel:
public class ProductsListViewModel
{
public List<Product> Products { get; set; }
public PagingInfo PagingInfo { get; set; }
public string CurrentCategory { get; set; }
}
Here is my ProductController's List Action: When I debug the application, at the click at page 2, category parameter is null.
public ViewResult List(string category, int page = 1)
{
ProductsListViewModel model = new ProductsListViewModel
{
Products = repository.Products
.Where(p => category == null || p.ProductCategory.Equals(category))
.OrderBy(p => p.ProductID)
.Skip((page - 1) * PageSize).Take(PageSize).ToList(),
PagingInfo = new PagingInfo
{
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = category == null ?
repository.Products.Count() :
repository.Products.Where(e => e.ProductCategory == category).Count()
}
};
model.CurrentCategory = category;
return View(model);
}
Here is my List View:
#model SportsStore.WebUI.Models.ProductsListViewModel
#{
ViewBag.Title = "Products";
}
#foreach (var p in Model.Products)
{
<div class="item">
#Html.Partial("ProductSummary", p)
</div>
}
<div class="pager">
#Html.PageLinks(Model.PagingInfo, x => Url.Action("List", new { page = x, ProductCategory = Model.CurrentCategory }))
ProductSummary is a partial view that views the product. Pagelinks is a extention methods:
public static MvcHtmlString PageLinks(this HtmlHelper html, PagingInfo pagingInfo,
Func<int, string> pageUrl)
{
StringBuilder result = new StringBuilder();
for (int i = 1; i <= pagingInfo.TotalPages; i++)
{
TagBuilder tag = new TagBuilder("a"); // Construct an <a> tag
tag.MergeAttribute("href", pageUrl(i));
tag.InnerHtml = i.ToString();
if (i == pagingInfo.CurrentPage)
tag.AddCssClass("selected");
result.Append(tag.ToString());
}
return MvcHtmlString.Create(result.ToString());
}
As pictured above, when I click page 2, it gets every product, rather than car. How can I solve it?
Thanks in advance.
NOTE: Routes has been added below:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(null,
"",
new
{
controller = "Product",
action = "List",
category = (string)null,
page = 1
}
);
/*
*http://localhost:56701/?page=2 olmasındansa http://localhost:56701/Page4 olmasını sağlayan kod parçacığı.
*
*/
routes.MapRoute(null,
"Page{page}",
new { controller = "Product", action = "List", category = (string)null },
new { page = #"\d+" }
);
routes.MapRoute(null,
"{category}",
new { controller = "Product", action = "List", page = 1 }
);
routes.MapRoute(null,
"{category}/Page{page}",
new { controller = "Product", action = "List" },
new { page = #"\d+" }
);
routes.MapRoute(null, "{controller}/{action}");
}
}
NOTE 2:
Here is the result when I click page 2 of the Car category:
As you see below, at the page 2, every car items exist. (Blue rectangle). But I do no want to see page 3 and 4 at the bottom of the page (Red rectangle).
Thanks in advance.
The solution has implemented in the book, and it seems it has been escaped from my attention.
Two revisions should be made in the source code, one in List.cshtml :
<div class="pager">
#Html.PageLinks(Model.PagingInfo, x => Url.Action("List", new { page = x, category = Model.CurrentCategory }))
Another is in the List action of the ProductController:
public ViewResult List(string category, int page = 1)
{
ProductsListViewModel viewModel = new ProductsListViewModel
{
Products = repository.Products
.Where(p => category == null || p.ProductCategory == category)
.OrderBy(p => p.ProductID)
.Skip((page - 1) * PageSize)
.Take(PageSize).ToList(),
PagingInfo = new PagingInfo
{
CurrentPage = page,
ItemsPerPage = PageSize,
**TotalItems = category == null ?
repository.Products.Count() :
repository.Products.Where(e => e.ProductCategory == category).Count()**
},
CurrentCategory = category
};
return View(viewModel);
}
TotalItems attribute shall be updated as mentioned above.
I have a route defined as follows in MVC:
routes.MapRoute(
name: "ContentNavigation",
url: "{viewType}/{category}-{subCategory}",
defaults: new { controller = "Home", action = "GetMenuAndContent", viewType = String.Empty, category = String.Empty, subCategory = String.Empty });
If I navigate to http://example.com/something/category-and-this-is-a-subcategory
It fills the variables as:
viewType: "something"
category: "category-and-this-is-a"
subCategory: "subcategory".
What I want is for the word before the first dash to always go into category, and the remaining into subcategory. So it would produce:
viewType: "something"
category: "category"
subCategory: "and-this-is-a-subcategory"
How can I achieve this?
One possibility is to write a custom route to handle the proper parsing of the route segments:
public class MyRoute : Route
{
public MyRoute()
: base(
"{viewType}/{*catchAll}",
new RouteValueDictionary(new
{
controller = "Home",
action = "GetMenuAndContent",
}),
new MvcRouteHandler()
)
{
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var rd = base.GetRouteData(httpContext);
if (rd == null)
{
return null;
}
var catchAll = rd.Values["catchAll"] as string;
if (!string.IsNullOrEmpty(catchAll))
{
var parts = catchAll.Split(new[] { '-' }, 2, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length > 1)
{
rd.Values["category"] = parts[0];
rd.Values["subCategory"] = parts[1];
return rd;
}
}
return null;
}
}
that you will register like that:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add("ContentNavigation", new MyRoute());
...
}
Now assuming that the client requests /something/category-and-this-is-a-subcategory, then the following controller action will be invoked:
public class HomeController : Controller
{
public ActionResult GetMenuAndContent(string viewType, string category, string subCategory)
{
// viewType = "something"
// category = "category"
// subCategory = "and-this-is-a-subcategory"
...
}
}
I'm new to asp.net mvc. I have index method with parameter id :
public ActionResult Index(int id)
{
var dc = new ServicesDataContext();
var query = (from m in dc.Mapings
where m.CustomerID == id
select m);
// var a = dc.Customers.First(m => m.CustomerId == id);
// ViewData.Model = a;
// return View();
return View(query);
}
Now when I try to redirect to index from edit i get an error " The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Index(Int32)' in 'MVCServices.Controllers.CustomerserviceController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
[HttpPost]
public ActionResult Edit( FormCollection form)
{
var id = Int32.Parse(form["CustomerServiceMappingID"]);
var datacontext = new ServicesDataContext();
var serviceToUpdate = datacontext.Mapings.First(m => m.CustomerServiceMappingID == id);
TryUpdateModel(serviceToUpdate, new string[] { "CustomerID", "ServiceID", "Status" }, form.ToValueProvider());
if (ModelState.IsValid)
{
try
{
var qw = (from m in datacontext.Mapings
where id == m.CustomerServiceMappingID
select m.CustomerID).First();
datacontext.SubmitChanges();
//return Redirect("/Customerservice/Index/qw");
return RedirectToAction("Index", new { qw = qw });
}
catch{
}
}
return View(serviceToUpdate);
}
This is the View:
#Html.ActionLink("Back to List", "Index")
The id in the Index method turns out to be the customerid fetched from another controller while id in Edit is from another table.Can you please let me know the mistake I've been doing and how to solve it?
Do this in the Edit action:
return RedirectToAction("Index", new { id = qw });
I have an action defined like so:
public ActionResult Foo(int[] bar) { ... }
Url's like this will work as expected:
.../Controller/Foo?bar=1&bar=3&bar=5
I have another action that does some work and then redirects to the Foo action above for some computed values of bar.
Is there a simple way of specifying the route values with RedirectToAction or ActionLink so that the url's get generated like the above example?
These don't seem to work:
return RedirectToAction("Foo", new { bar = new[] { 1, 3, 5 } });
return RedirectToAction("Foo", new[] { 1, 3, 5 });
<%= Html.ActionLink("Foo", "Foo", new { bar = new[] { 1, 3, 5 } }) %>
<%= Html.ActionLink("Foo", "Foo", new[] { 1, 3, 5 }) %>
However, for a single item in the array, these do work:
return RedirectToAction("Foo", new { bar = 1 });
<%= Html.ActionLink("Foo", "Foo", new { bar = 1 }) %>
When setting bar to an array, it redirects to the following:
.../Controller/Foo?bar=System.Int32[]
Finally, this is with ASP.NET MVC 2 RC.
Thanks.
There are a few ways to do this. If you want to keep it stateless avoid using
TempData and create a action filter.
Somthing like this:
ActionFilter:
public class BindArrayAttribute:ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var keys = filterContext.HttpContext.Request.QueryString.AllKeys.Where(p => p.StartsWith("id"));
var idArray = new int[keys.Count()];
var counter = 0;
foreach (var key in keys)
{
var id = filterContext.HttpContext.Request.QueryString[key];
idArray[counter] = int.Parse(id);
counter++;
}
filterContext.ActionParameters["id"] = idArray;
base.OnActionExecuting(filterContext);
}
}
Controller:
[HttpPost]
public ActionResult Index(ItemModel model)
{
var dic = new RouteValueDictionary();
var counter = 0;
foreach (var id in model.SelectedItemIds)
{
dic.Add("id" + counter, id);
counter++;
}
return RedirectToAction("Display", dic);
}
[HttpGet]
[BindArray]
public ActionResult Display(int[] id = null)
{
return View(id);
}
I'm not sure how to accomplish that using the existing helpers. But you could write your own method to do so.
Here's something I threw together:
public static string EnumerableActionLink(this HtmlHelper htmlHelper, string linkText, string controllerName, string actionName, IEnumerable enumerable, string variableName)
{
var builder = new StringBuilder(string.Format("/{0}/{1}?", controllerName, actionName));
foreach (var item in enumerable)
builder.Append(string.Format("{0}={1}&", variableName, item));
return string.Format("{1}", builder, linkText);
}
Usage example:
<%= Html.EnumerableActionLink("Foo", "Foo", "Foo", new[] { 1, 3, 5 }, "bar")%>
<%= Html.ActionLink("Foo", "Foo", "Foo",
new[] { 1, 3, 5 }.Aggregate(string.Empty, (a, x) => a += "bar=" + x + "&"))
%>