I am relatively new to ASP.NET MVC, and am very impressed with the clarity of the platform so far. However, there is one aspect that I find uncomfortable.
At first, I accepted the fact that when I say
return View();
I am calling a helper method that returns an ActionResult, and makes some assumptions about which view to present, route values, etc. But lately I have been writing code that looks more like this:
return View("Index", new { id = myID })
because it is immediately clear to me what's happening by reading that single line of code.
Lately I have been struggling with the fact that I can have an Index.ASPX view open on the tabs, and I can't immediately tell where it comes from because the IDE doesn't highlight the current tab in the Object Explorer. I haven't resorted to changing the names of the files to ControllerNameIndex.ASPX, but I do put a title in the view that is more specific. Still, it doesn't help much.
How do you deal with these kinds of ambiguities?
I think you answered your own question.
There's no hard rule preventing you from calling your views very specific names, such as "ListOfFooBars" or "EditFizzBuzz" or "AddNewGeeblup". The naming convention for the default view engine only specifies that there's a folder corresponding to your model name under views, and there's an ASPX or ASPC file under that folder that corresponds to your view name.
Related
I've looked at a dozen or so ways to do this and I'm having a very hard time getting things to work. The issues I've run into fall into one of two categories:
1) A full MVC setup is assumed in the examples I'm looking at. In my case, I'm sending an email from a WebApi project and will not be using any of the pre-wired MVC view functionality provided by the ASP.NET project stub.
2) Libraries are asking for some complex setup I don't really think I need, specifically RazorEngine asking me to set up a TemplateManager, when all I need to do is give a .cshtml file a model and get the parsed results back.
Pardon the noob question; I'm working on my first .NET project here. Thanks!
I had to do the same thing for different reasons a while ago. I had found this class that I used to render the view into a string: https://github.com/RickStrahl/WestwindToolkit/blob/master/Westwind.Web.Mvc/Utils/ViewRenderer.cs
Use it like this:
var r = new ViewRenderer();
var renderedView = r.RenderViewToString("~/Views/MyView.cshtml");
If you need to pass a model to the view, call it like this:
var renderedView = r.RenderViewToString("~/Views/MyView.cshtml", model);
Where model is what your view expects.
While the #Html.Actionlink() helper is very convenient for building <a> elements in the .cshtml files, is it possible to construct them inside C# strings, such that they are subsequently rendered correctly in the HTML output?
For example, if I assign a string variable a value similar to the following:
Book.ReadMore = "Click #Html.ActionLink(\"this link\", \"About\", \"Home\") to read more.";
And then I try to display it (the literal text plus the link) through my .cshtml page, using code similar to:
<p>#Model.ReadMore</p>
All I get in the browser is the whole string exactly as I typed it, including the #Html... etc:
Click #Html.ActionLink("this link", "About", "Home") to read more.
Now, for proper SoC, I know that it's not the best of practices to have HTML stuff included in C# code, but is it at all possible to get the proper <a> link in this scenario, instead of the string itself?
EDIT: More information - This string is just one item in a collection of about 20-30 strings (displayed using a for loop in the View). Only a small handful of those items need a link (which is different in each case). Since, as mentioned above, I agree that it's obviously not good practice to use Razor/HTML in Model code, I'm trying to get a simple approach (if possible) which would give me the flexibility of building the link somewhere at the right place, while still yielding the maintainability of MVC SoC.
There must be a "right" way of doing this, which is simple yet maintainable.
Your model should not contain HTML, that's a view concern and belongs in view code. Probably you should be using a Razor helper.
In your App_Code folder (create one if you don't have one), add a file, ReadMoreHelpers.cshtml:
#helper ReadMore() {
<text>Click #Html.ActionLink("this link", "About", "Home") to read more.</text>
}
Then in any view:
#ReadMoreHelpers.ReadMore()
And that will output what you want. If you insist on putting that property in your view, you could do:
Book.ReadMore = "Click " + #Html.ActionLink("this link", "About", "Home").ToHtmlString() + " to read more.";
Then in your view, make sure you use Raw:
#Html.Raw(Book.ReadMore)
However, I couldn't recommend more strongly that you do not put HTML in your model properties.
I don't think so. The Razor view engine will interpret the ActionLink code during run-time while stuffing it as part of a C# string will be interpreted during compile time.
I'm trying to create a strongly typed model for one of my Views in MVC. The model is the result of a LINQ GroupBy query so it is the type shown below (grouping employees by first letter of surname).
#model IQueryable<IGrouping<string, Employee>>
I'm unsure why but it doesn't let me have a model of this type. The error message I get is:
An opening "<" is missing the corresponding closing ">". Which is incorrect.
I know I can create a view specific model and populate that instead but I'd like to know why this model doesn't seem to work?
By default, a very limited set of namespaces are available for direct use in razor views. Try to expand it to fully qualified names and see if the problem persists:
#model System.Linq.IQueryable<System.Linq.IGrouping<string, Name.Space.Employee>>
I don't know why you'd be getting this error, since you appear to be using correct Razor code. It's possible that there's actually a bug elsewhere in the page that is being made manifest through this incorrect error message.
A workaround, which may help you determine the real source of the bug, would be to create your own strongly-typed model class, which could have this data as its property:
public class EmployeeListViewModel
{
public IQueryable<IGrouping<string, Employee>> EmployeesByCompanyTitle {get;set;}
}
(There are those who would argue that this is a better approach anyway, since you can now add information to your view model more easily.)
does it reload the entire page or does it have the intelligence to only send the necessary js to update the needed parts of the page that have changed?
if it does the latter that would be a god send, however im probably being dreamful. it probably returns the entire view without any regard, right?
edit: answer seems to be no, everything is returned.
edit added:
do you think it would be difficult to write a framework where mvc compares last html it output to the current html we want to output, and instead of sending the entire html, figure out what has changed and generate js code that will do the updating as compared to previous html? (presuming nothing was manually changed on the client using js)... maybe an idea for a codeplex project? or maybe something like this exists?
Well, it entirely depends on how you do it.
You can return anything you want, when using ajax its common to return your data in JSON. Example:
public ActionResult GetCustomers()
{
if(Request.IsAjaxRequest)
return Json(db.GetCustomers());
return View(db.GetCustomers());
}
This will return all customers Json encoded if the request was made using Ajax.
You can stil return anything you want, if you want to return a view, it's just to
return View(model);
If you dont want to return the layout (master page), just return the MasterPageFile directive from your view.
And no, it does not reload the entire page, that's why it's called Ajax.
Frankly, what happens on the client side is of no concern to MVC. :-) It does not know whether the call was made by the browser engine or the ECMA script.
And since you are asking about Ajax call, the responsibility with dealing with the result falls onto your script (or whatever JS framework you're using).
I'm currently trying to user actionlink helpers in a way that I don't think was described in NerdDinner.
Lets say I am on this page
/Dinners/
and on that page there is a list of dinners, ok fine and working
now lets say I want to goto a new section of the site, which I have created a new controller MenuItemsController
so lets say I want to goto a new part of the website that manages menu items.
So going to
/menuitems/3
would bring up all the menu items assoicated with dinner id 3.
This is also working.
I am having trouble, linking to each of the menu item pages, because when I use the actionlink code, without much modification i get this
dinner1 = link /dinners/menuitems/3
rather than
dinner = link /menuitems/3
The actionlink code i am trying is
<%= Html.ActionLink("Menu Items", "/menuitems", new { id=item.id })%>
you can see the / there. This feels wrong.
I wasn't sure if this post was talking about the same problem or not.
how do i have links to root controllers in site.master in asp.net mvc
Are action links the completely wrong thing for me to be using here, becuase they are binded directly to the controller I am currently inside of?
If so, what would be the best method for me to achieve what I am trying to do, and also add further complexity like linking to create/edit/delete methods?
Just get rid of the slash and specify the controller and action explicitly:
<%= Html.ActionLink("Menu Items", "Item", "menuitems",
new RouteValueDictionary { { "id", item.id } })%>
You don't give an action name in your examples, so I guessed "Item." Insert the correct action name, obviously.
The current controller name is used if you use one of the ActionLink overloads which don't take a controller name.
I've written an in-depth explanation of routing, ActionLink, and more.
I oddly after much searching all day just found this page,
http://devlicio.us/blogs/derik_whittaker/archive/2008/03/06/link-building-101-with-asp-net-mvc.aspx
it seems like method 3 may be what I need, I'll try it when I get home.