ASP.NET MVC 3 won't recognise .cshtml view files - asp.net-mvc-3

I have ported an mvc 3 app from vs 2010 to vs2012.
The ported app is using .NET 4.
All the old bits work, but with a new view, created in vs 2012, the view engine is not looking for .cshtml files for the view.
For example, when the user requests the index action on the Welcome controller in the Solicitors area, the url is:
mysite.com/solicitors/welcome/gg
(where gg is the user name). In that case, the error that comes back is:
The view 'Index' or its master was not found or no view engine
supports the searched locations. The following locations were
searched: ~/Areas/Solicitors/Views/Welcome/Index.aspx
~/Areas/Solicitors/Views/Welcome/Index.ascx
~/Areas/Solicitors/Views/Shared/Index.aspx
~/Areas/Solicitors/Views/Shared/Index.ascx ~/Views/Welcome/Index.aspx
~/Views/Welcome/Index.ascx ~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx ~/Areas/Solicitors/Views/Welcome/gg.master
~/Areas/Solicitors/Views/Shared/gg.master ~/Views/Welcome/gg.master
~/Views/Shared/gg.master ~/Areas/Solicitors/Views/Welcome/gg.cshtml
~/Areas/Solicitors/Views/Welcome/gg.vbhtml
~/Areas/Solicitors/Views/Shared/gg.cshtml
~/Areas/Solicitors/Views/Shared/gg.vbhtml ~/Views/Welcome/gg.cshtml
~/Views/Welcome/gg.vbhtml ~/Views/Shared/gg.cshtml
~/Views/Shared/gg.vbhtml
I have already added the following key to appsettings in web.config, but it makes no difference.
<add key="webpages:Version" value="1.0" />
EDIT:
Route in SolictorAreaRegistration.cs:
context.MapRoute(
"Solicitors_Welcome",
"Solicitors/Welcome/{nameUser}",
new { controller = "Welcome", action = "Index", nameUser = UrlParameter.Optional }
);
EDIT 2:
Using RouteDebug, I can see that the correct controller and action are found.
Route Data
Key Value
nameUser: gg
controller: Welcome
action: Index
Data Tokens
Key Value
Namespaces: System.String[]
area: Solicitors
UseNamespaceFallback: False
EDIT 3:
The route is found correctly, as I can see from debugging: the Index action is hit.
The problem happens when the line call the view is called:
namespace MyApp.Areas.Solicitors.Controllers
{
[Authorize]
public partial class WelcomeController : Controller
{
//
// GET: /Solicitors/Welcome/
public virtual ActionResult Index(string nameUser)
{
return View("Index", nameUser);
}
}
}

OK, got to the bottom of it:
The Problem:
The problem is that the model of my view is of type string. In my action, I was passing in a string as the model parameter:
public virtual ActionResult Index(string nameUser)
{
return View("Index", nameUser);
}
This will clash with one of the overloads of Controller.View(...):
View(string, string)
The second parameter expects the name of a layout file. When you do this, MVC goes off looking for a layout file with a name of the value of your string, which could be, for example:
"Hello, World. I'm an idiot, but if you give me a decent error message, I might be able to fix the bug."
Obviously, a layout file with that name doesn't exist. Nor does a layout file called "gg" either (my (test) solicitor's username).
The Solution:
The solution is simple:
Specify that the second parameter is the model, not the layout.
public virtual ActionResult Index(string nameUser)
{
return View("Index", model: nameUser);
}
Useful Article:
To view an extended discussion of this very issue, see the following article:
MVC Gotcha: Beware when using your view's model is a string
Many thanks to heartysoft.com for the enlightenment.

It is looking as you can see from the error message:
~/Areas/Solicitors/Views/Welcome/gg.cshtml
If you need to look for the Index view then you need to specify it:
http://mysite.com/solicitors/welcome/index/gg

Related

Cannot view my new MVC 4 application

I just created a new basic MVC 4 application in VS 2010. I just clicked the play button to test it came up in the web browser and I'm getting the following page:
I think I need to change my virtual path to something but I don't know what.
EDIT: Can't see what it says properly in the picture:
Server Error in '/' Application.
--------------------------------------------------------------------------------
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /
If you created an Empty Project you will need to create a HomeController with an Index Action. You will also need to create a View in ~/Views/Home/ called Index.
The other project templates create this for you but the Empty Project does not.
public class HomeController : Controller
{
public ActionResult Index()
{
return View()
}
}
No one person gave me the full answer. So this is an amalgamation of #MattiVirkkunen and #BrettAlfred
Add this within RouteConfig.cs
routes.MapRoute(
name: "Default",
url: "",
defaults: new { controller = "Home", action = "Home" }
);
Add this within HomeController.cs
public ActionResult Login()
{
return View();
}
Kya Neeta MVC me neyi ho Kya?? I am too :)
I think u have created a start-up page in your applicaition.
Type Http: //localhost:8080/Home/Index in your url
http: //localhost:/ControllerName/ActionName
if that does not work please create a new MVC application from scratch.

C# MVC RedirectToAction not working?

So I want to create a new view in my MVC application that allows a user to enter parameters for searching. I want to pass these parameters to another View/Controller and I want the controller to call an action called "Search" to handle these parameters and return the correct data. However, when I try to "Redirect" it is giving me a problem. It says the resource cannot be found,
The view 'Search' or its master was not found or no view engine supports the searched locations.
The following locations were searched:
~/Views/Question/Search.aspx
This is the code.
[HttpPost]
public ActionResult HandleForm()
{
SearchQuery search = new SearchQuery();
if(Request["QuestionID"].Trim()!="")
search.QuestionID = Convert.ToInt32(Request["QuestionID"].Trim());
return RedirectToAction("Search", "Question");
}
However, if I change "Search" to "Index" it loads the page I desire because it opens the view within that page. It does not call the search action. Why is this method returning the View when every example I've read states that the name of the Action needs to be passed?
For those who are wondering this is my global.asax routing info
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
Last but not least, I have yet to look into how to pass these parameters, but I hope it won't be too much extra work once I can figure out why this is not working as desired.
Go to the Views/Questions directory and make sure there is a file called Search.cshtml. If it does exist also then make sure that this view has a corresponding action method, something like:
public class QuestionController : Controller
{
public ActionResult Search()
{
}
}
If you are in same controller then write:
return RedirectToAction("Search");
or if your search action is in other controller then write:
return RedirectToAction("Search","your Controller Name Here");

ASP.NET MVC 3 - Setting up routes

I'm migrating an ASP.NET web forms application to ASP.NET MVC 3. I kind of understand routing, but I sort of don't. In my application, I have created three .cshtml files in the directory located at /internal/products/find/. For the sake of demonstration, those .cshtml files are named "view1.cshtml", "view2.cshtml", and "view3.cshtml".
I have a controller named "InternalController". My goal is to use InternalController for all of the locations inside the /internal path. I'm not sure if what I'm trying to do is allowed. I assume it is. Either way, at this time, I have the following in InternalController:
public ActionResult View1()
{
return View();
}
public ActionResult View2()
{
return View();
}
public ActionResult View3()
{
return View();
}
In my global.asax.cs file, I'm trying to register the routes to these views as follows:
routes.MapRoute(
"View1",
"{controller}/products/find/view1",
new { controller = "Internal", action = "View1" }
);
routes.MapRoute(
"View2",
"{controller}/products/find/view2",
new { controller = "Internal", action = "View2" }
);
routes.MapRoute(
"View3",
"{controller}/products/find/view3",
new { controller = "Internal", action = "View3" }
);
Whenever I try to visit /internal/products/find/view1 in my browser, I see the ASP.NET error screen and it says:
The view 'View1' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/internal/View1.aspx
~/Views/internal/View1.ascx
~/Views/Shared/View1.aspx
~/Views/Shared/View1.ascx
~/Views/dashboard/View1.cshtml
~/Views/dashboard/View1.vbhtml
~/Views/Shared/View1.cshtml
~/Views/Shared/View1.vbhtml
What am I doing wrong? The path /internal/products/find/view1 is the most important part for me. Ideally, I would like to expose that in InternalController everytime. But I'm having a rough go at it. What am I doing wrong?
Thanks!
When you write
routes.MapRoute(
"View1",
"{controller}/products/find/{action}",
new { controller = "Internal", action = "View1" }
);
it means that whenever user writes into his browser:
http://mysite.com/blahblah/products/find/blahblahview
it will activate action view1 inside controller blahblahview. But it doesn't mean that view1.cshtml file is at that path. Actually, asp.net mvc looks for views at directories defined by convention...and convetion is:
~/Views/ControllerName/ViewName
so, your view should be in a folder:
~/Views/Internal/View1.cshtml
Unlike ASP.NET WebForms you are used to, ASP.NET MVC is pretty much driven by naming conventions as you could probably see (you always name your controllers like BlahBlah*Controller*, you always place your views inside Views folder etc... Read some tutorials here and catch up with basics.

View and controller in asp.net mvc3 - controller should match a view one to one?

I have a very typical situation in any application, where i have the following functionality:
create new record
edit existing record
so other irrelevant actions
IMO, creating and editing should be served by the same view, but different actions. But it appears that I have to have the action name match the view name....would you use partial views for this? I would rather not complicate this scenario - which is very simple and appears in virtually every web app.
Action can return a view with a diferent name this way:
public ActionResult OneName()
{
return View("OtherName");
}
If you don't specify the view name (View("") then the view will be the view with the action name
Partial views are an excellent answer. I'd suggest you look at how the MvcScaffold NuGet package does it. See here or get the package in Visual Studio.
I'd simply use the same action altogether and use the ID to determine if this is a new record or updating an existing one:
/Forum/Post/Edit/0 create a new record
/Forum/Post/Edit/10457 update a record with ID 10457
However, since you insist on using different actions, why not simply create 2 actions, both returning the same view?
public class PostController : Controller
{
public ActionResult Create(Post post)
{
// work your magic...
return View("Edit", post);
}
public ActionResult Update(Post post)
{
// work your magic...
return View("Edit", post);
}
}
If this doesn't work in your scenario, you're pretty much left with partial views.

Weird behavior of urlrewriting in MVC3 with razor viewengine

I am working on a project which adopted ASP.NET MVC3(Razor) tech.
Now, I have a controller below:
public class Home: Controller
{
public ActionResult Result(string id)
{
return View(id);
}
}
and I have set MapRoute as below:
context.MapRoute(
"Home_result",
"Home/Result/{id}",
new { controller="Home", action = "Result"}
);
and it was suposed to display a View which named "Result" when I typed the url http://domain.com/Home/Result/abc123 in the browser. However it didn't.
Instead it gave me an exception below:
The view 'Result' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Home/abc123.cshtml
~/Views/Home/abc123.vbhtml
~/Views/Shared/abc123.cshtml
~/Views/Shared/abc123.vbhtml
It is strange isn't it?
Can anyone help me to figure out what mistakes I've made?
return View(id);
Returns a view with the name of ID's value (.cshtml), not the view with the name result.cshtml. I think this is because Id is a string. Are you trying to pass the id to the view?
To return the view matching the name of your controller's action simply use
return View();
If you want to pass that value to the view, for what ever crazy reason, using the viewbag is the easiest way since the string id is being used to declare a view name.
ViewBag.ID = id;
return View();
Then in the view just use the value you stored. And yes Razor HTML encodes by default.
#ViewBag.ID

Resources