Storing ActionLink in model or RouteValueDictionary in model - asp.net-mvc-3

I wish to store an action link in the model.
Something like
public MvcHtmlString ActionLink_New
{
get { return Html.ActionLink("new", "Edit", "News", new { Area = "Admin" }, null); }
}
It appears the model needs a webviewpage context.
Failing that, I thought I would store just the route values.
public RouteValueDictionary[] RouteValue_New
{
get { return new RouteValueDictionary[] { Area = "Admin" }; }
}
//View
#Html.ActionLink("new", "Edit", "News", Model.RouteValue_New, null)
The Area in the property is red. Is either or both scenario achievable. What do i need to add to get this to work, thanks.

try this
public object RouteValue_New
{
get {
return new { Area = "Admin" };
}
}

Related

$select on navigation property / WebApi 2.0 / OData 4

Given the following simple OData 4 controller (please see below), how do I $select just the cities?
http://localhost//api/Customers?$select=Location
Gives me:
{
"#odata.context":"http://localhost/api/$metadata#Customers(Location)","value":[
{
"Location":{
"Country":"Ireland","City":"Sligo"
}
},{
"Location":{
"Country":"Finland","City":"Helsinki"
}
}
]
}
But I don't know how to drill down one deeper so that I just get the cities. Is this even possible?
public class CustomersController : ODataController
{
private List<Customer> customers = new List<Customer>()
{
new Customer
{
CustomerId = 1,
Location = new Address
{
City = "Sligo",
Country = "Ireland"
}
},
new Customer
{
CustomerId = 2,
Location = new Address
{
City = "Helsinki",
Country = "Finland"
}
}
};
[EnableQuery]
public List<Customer> Get()
{
return customers;
}
}
The grammar for $select does not allow a path expression like Location/City. Your best bet is to define an OData function bound to the Customers entity set. E.g.,
[HttpGet]
public IEnumerable<string> GetCities()
{
return customers.Select(c => c.Location.City);
}
And invoke it as follows:
GET http://localhost/api/Customers/ServiceNamespace.GetCities

How to redirect to Details View?

This is my LearnController and here is the create.
[HttpPost]
public ActionResult Create(Learn learn)
{
if (ModelState.IsValid)
{
db.Learns.Add(learn);
db.SaveChanges();
return RedirectToAction("Details", new { id = learn.ModuleId });
}
ViewBag.ModuleId = new SelectList(db.Modules, "ModuleId", "Code", learn.ModuleId);
return View(learn);
}
Here is the detail in my LearnController
public ViewResult Details(int id)
{
var mod = db.Modules.Include("Learns").Single(g => g.ModuleId == id);
return View(mod);
}
In my create view of the learning controller, I place a HTMLActionLink but I can't seem to be redirected. Is there something wrong with my codes?
#Html.ActionLink("Back to List", "Details")
This is the error.
The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ViewResult Details(Int32)' in 'Module1.Controllers.LearnController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters
The link would need to be #Html.ActionLink("Back to List", "Details", new { id = # }) where # is the id of the Module to display. So when you create a new Learn the GET method would need to be something like
public ActionResult Create(int ID) // ID is the ModuleId your creating the Learn for
{
Learn model = new Learn();
model.ModuleID = ID;
return View(model);
}
and in the view
#model Learn
....
#Html.ActionLink("Back to List", "Details", new { id = Model.ModuleID })
This is assuming that the Details view contains a link to create a new Learn for the Module, where the link would be #Html.ActionLink("Add new Learn", "Create", new { id = Model.ID})
If you can create a new Learn from some other view (where you don't have access to the ID property of Module), and where the view to create a new Learn allows you to select the Module form a drop down list, then you would need javascript/jquery to update the href value of the link based on the selected Module
"The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32", the parameters should be nullable type, change to this
public ViewResult Details(int? id)
{
try
{
if (id.HasValue)
{
var mod = db.Modules.Include("Learns").Single(g => g.ModuleId == id);
if (mod == null)
throw new ArgumentException("Invalid ID");
return View(mod);
}
else
{
throw new ArgumentException("Invalid ID");
}
}
catch (ArgumentException ex)
{
return View(new Modules()); // assumed Details view model is Modules class
}
catch
{
return View(new Modules()); // assumed Details view model is Modules class
}
}
or
public ViewResult Details(string id)
{
try
{
int intId;
if(int.TryParse(id, out intId))
{
var mod = db.Modules.Include("Learns").Single(g => g.ModuleId == intId);
if (mod == null) throw new ArgumentException("Invalid ID");
return View(mod);
}
else
{
throw new ArgumentException("Invalid ID");
}
}
catch (ArgumentException ex)
{
return View(new Modules()); // assumed Details view model is Modules class
}
catch
{
return View(new Modules()); // assumed Details view model is Modules class
}
}
Update
I think I misunderstood your question, all you need to do is change
#Html.ActionLink("Back to List", "Details" })
to
#Html.ActionLink("Back to List", "Details", new { id = Model.ModuleId })
as suggested by Stephen Muecke

how to handle hange my routes value?

i have an area and change my route to this
public class WeblogsAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Weblogs";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Weblogs_default",
"Weblogs/{controller}/{action}/{blogName}/{post}",
new { action = "Index",
blogName = UrlParameter.Optional,post=UrlParameter.Optional}
);
}
}
and it is my index
public ActionResult Index(string blogName,int post)
{
return View();
}
it works fine by this:
http://localhost:2927/Weblogs/Blogs?blogName=Myco&Post=3
but works not by
http://localhost:2927/Weblogs/Blogs?blogName=Myco
what is the problem?
how can i change my rout to works with this URL:
http://localhost:2927/Weblogs/Blogs/Myco/3
"myco" is blog name and 3 is post number.
is it possible?
Remove your action and controller tokens from your route. Modify it to be like so:
context.MapRoute(
"Weblogs_default",
"Weblogs/Blogs/{blogName}/{post}",
new { action = "Index",
Controller = "Blogs",
blogName = UrlParameter.Optional,
post=UrlParameter.Optional}
);

MVC3 Areas routing conflict

Question: i want my route to be like that
/admin/main/category/1 -> 1 == ?page=1
i don't want page=1 to be seen
My Controller
public class MainController : BaseController
{
private const int PageSize = 5; //pager view size
[Inject]
public ICategoryRepository CategoryRepository { get; set; }
public ActionResult Index()
{
return View();
}
public ActionResult Category(int page)
{
//int pageIndex = page.HasValue ? page.Value : 1;
int pageIndex = page != 0 ? page : 1;
return View("Category", CategoryViewModelFactory(pageIndex));
}
/*
*Helper: private instance/static methods
======================================================================*/
private CategoryViewModel CategoryViewModelFactory(int pageIndex) //generate viewmodel category result on pager request
{
return new CategoryViewModel
{
Categories = CategoryRepository.GetActiveCategoriesListDescending().ToPagedList(pageIndex, PageSize)
};
}
}
public class AdminAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "admin";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRouteLowercase(
"AdminCategoryListView",
"admin/{controller}/{action}/{page}",
new { controller = "Category", action = "Category", page = "1" },
new { id = #"\d+" },
new[] { "WebUI.Areas.Admin.Controllers" }
);
}
}
My Exception:
The parameters dictionary contains a null entry for parameter 'page'
of non-nullable type 'System.Int32' for method
'System.Web.Mvc.ActionResult Category(Int32)' in
'WebUI.Areas.Admin.Controllers.MainController'. An optional parameter
must be a reference type, a nullable type, or be declared as an
optional parameter. Parameter name: parameters
Thank you all in advance.
Make sure that in your Admin area route registration you have defined the {page} route token instead of {id} which is generated by default:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{page}",
new { action = "Index", page = UrlParameter.Optional }
);
}
Now when you are generating links make sure you specify this parameter:
#Html.ActionLink(
"go to page 5", // linkText
"category", // actionName
"main", // controllerName
new { area = "admin", page = "5" }, // routeValues
null // htmlAttributes
)
will emit:
go to page 5
and when this url is requested the Category action will be invoked and passed page=5 parameter.

Can I display contents of Application or Cache objects using Glimpse in an MVC project?

The ASP.NET WebForms trace output has a section for Application State. Is it possible to see the same using Glimpse?
In my home controller's Index() method, I tried adding some test values, but I don't see the output in any of the Glimpse tabs.
ControllerContext.HttpContext.Application.Add("TEST1", "VALUE1");
ControllerContext.HttpContext.Cache.Insert("TEST2", "VALUE2");
I didn't see anything in the documentation either.
I don't think that there is an out-of-the-box support for this, but it would be trivial to write a plugin that will show this information.
For example to show everything that's stored in the ApplicationState you could write the following plugin:
[Glimpse.Core.Extensibility.GlimpsePluginAttribute]
public class ApplicationStateGlimpsePlugin : IGlimpsePlugin
{
public object GetData(HttpContextBase context)
{
var data = new List<object[]> { new[] { "Key", "Value" } };
foreach (string key in context.Application.Keys)
{
data.Add(new object[] { key, context.Application[key] });
}
return data;
}
public void SetupInit()
{
}
public string Name
{
get { return "ApplicationState"; }
}
}
and then you get the desired result:
and to list everything that's stored into the cache:
[Glimpse.Core.Extensibility.GlimpsePluginAttribute]
public class ApplicationCacheGlimpsePlugin : IGlimpsePlugin
{
public object GetData(HttpContextBase context)
{
var data = new List<object[]> { new[] { "Key", "Value" } };
foreach (DictionaryEntry item in context.Cache)
{
data.Add(new object[] { item.Key, item.Value });
}
return data;
}
public void SetupInit()
{
}
public string Name
{
get { return "ApplicationCache"; }
}
}

Resources