The view or its master was not found or no view engine supports the searched locations - asp.net-mvc-4

Error like:The view 'LoginRegister' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/MyAccount/LoginRegister.aspx
~/Views/MyAccount/LoginRegister.ascx
~/Views/Shared/LoginRegister.aspx
~/Views/Shared/LoginRegister.ascx
~/Views/MyAccount/LoginRegister.cshtml
~/Views/MyAccount/LoginRegister.vbhtml
~/Views/Shared/LoginRegister.cshtml
~/Views/Shared/LoginRegister.vbhtml
Actually my page view page is ~/Views/home/LoginRegister.cshtml so what i do
and my RouteConfig is
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "MyAccount", action = "LoginRegister", id = UrlParameter.Optional }
);
}
}

Be careful if your model type is String because the second parameter of View(string, string) is masterName, not model. You may need to call the overload with object(model) as the second parameter:
Not correct :
protected ActionResult ShowMessageResult(string msg)
{
return View("Message",msg);
}
Correct :
protected ActionResult ShowMessageResult(string msg)
{
return View("Message",(object)msg);
}
OR (provided by bradlis7):
protected ActionResult ShowMessageResult(string msg)
{
return View("Message",model:msg);
}

Problem:
Your View cannot be found in default locations.
Explanation:
Views should be in the same folder named as the Controller or in the Shared folder.
Solution:
Either move your View to the MyAccount folder or create a HomeController.
Alternatives:
If you don't want to move your View or create a new Controller you can check at this link.

In Microsoft ASP.net MVC, the routing engine, which is used to parse incoming and outgoing URL Combinations, is designed with the idea of Convention over Configuration. What this means is that if you follow the Convention (rules) that the routing engine uses, you don't have to change the Configuration.
The routing engine for ASP.net MVC does not serve web pages (.cshtml). It provides a way for a URL to be handled by a Class in your code, which can render text/html to the output stream, or parse and serve the .cshtml files in a consistent manner using Convention.
The Convention which is used for routing is to match a Controller to a Class with a name similar to ControllerNameController i.e. controller="MyAccount" means find class named MyAccountController. Next comes the action, which is mapped to a function within the Controller Class, which usually returns an ActionResult. i.e. action="LoginRegister" will look for a function public ActionResult LoginRegister(){} in the controller's class. This function may return a View() which would be by Convention named LoginRegister.cshtml and would be stored in the /Views/MyAccount/ folder.
To summarize, you would have the following code:
/Controllers/MyAccountController.cs:
public class MyAccountController : Controller
{
public ActionResult LoginRegister()
{
return View();
}
}
/Views/MyAccount/LoginRegister.cshtml: Your view file.

In your LoginRegister action when returning the view, do below, i know this can be done in mvc 5, im not sure if in mvc 4 also.
public ActionResult Index()
{
return View("~/Views/home/LoginRegister.cshtml");
}

Check the build action of your view (.cshtml file) It should be set to content. In some cases, I have seen that the build action was set to None (by mistake) and this particular view was not deploy on the target machine even though you see that view present in visual studio project file under valid folder

This could be a permissions issue.
I had the same issue recently. As a test, I created a simple hello.html page. When I tried loading it, I got an error message regarding permissions. Once I fixed the permissions issue in the root web folder, both the html page and the MVC rendering issues were resolved.

Check whether the View (.ASPX File) that you have created is having the same name as mentioned in the Controller. For e.g:
public ActionResult GetView()
{
return View("MyView");
}
In this case, the aspx file should be having the name MyView.aspx instead of GetView.aspx

I got this error because I renamed my View (and POST action).
Finally I found that I forgot to rename BOTH GET and POST actions to new name.
Solution : Rename both GET and POST actions to match the View name.

If the problem happens intermittently in production, it could be due to an action method getting interrupted. For example, during a POST operation involving a large file upload, the user closes the browser window before the upload completes. In this case, the action method may throw a null reference exception resulting from a null model or view object. A solution would be to wrap the method body in a try/catch and return null. Like this:
[HttpPost]
public ActionResult Post(...)
{
try
{
...
}
catch (NullReferenceException ex) // could happen if POST is interrupted
{
// perhaps log a warning here
return null;
}
return View(model);
}

I had this same issue.
I had copied a view "Movie" and renamed it "Customer" accordingly.
I also did the same with the models and the controllers.
The resolution was this...I rename the Customer View to Customer1 and
just created a new view and called it Customer....I then just copied
the Customer1 code into Customer.
This worked.
I would love to know the real cause of the problem.
UPDATE
Just for grins....I went back and replicated all the renaming scenario again...and did not get any errors.

I came across this error due to the improper closing of the statement,
#using (Html.BeginForm("DeleteSelected", "Employee", FormMethod.Post))
{
} //This curly bracket needed to be closed at the end.
In Index.cshtml view file.I didn't close the statement at the end of the program. instead, I ended up closing improperly and ran into this error.
I was sure there isn't a need of checking Controller ActionMethod code because I have returned the Controller method properly to the View. So It has to be the view that's not responding and met with similar Error.

If you've checked all the things from the above answers (which are common mistakes) and you're sure that your view is at the location in the exceptions, then you may need to restart Visual Studio.
:(

In my case, I needed to use RedirectToAction to solve the problem.
[HttpGet]
[ControleDeAcessoAuthorize("Report/ExportToPDF")]
public ActionResult ExportToPDF(int id, string month, string output)
{
try
{
// Validate
if (output != "PDF")
{
throw new Exception("Invalid output.");
}
else
{
...// code to generate report in PDF format
}
}
catch (Exception ex)
{
return RedirectToAction("Error");
}
}
[ControleDeAcessoAuthorize("Report/Error")]
public ActionResult Error()
{
return View();
}

I ran into this a while ago and it drove me crazy because it turned out to be simple. So within my View I was using a grid control that obtained data for the grid via an http request. Once the middle tier completed my request and returned the dataset, I received the same error. Turns out my return statement was 'return View(dataset);' instead of 'return Json(dataset);

I couldn't find any solution to this problem, until I found out the files didn't exist!
This took me a long time to figure out, because the Solution Explorer shows the files!
But when I click on Index.cshtml I get this error:
So that was the reason for this error to show. I hope this answer helps somebody.

Related

Unable to create a Role using RoleManager in Blazor Serverside

I had some code using the RoleManager that I had copied from an MVC project to create roles in a Blazor project.
It compiles okay but when I step through the code it gets to that line and then appears to throw and exception, as it doesn't ever go to the next line. I am unable to catch an exception though.
Since my code didn't work I found code on the web and it behaved the same, so I changed how it was injected and I got a different error, so I found a third way of doing it and that too gets to the line that tests to see if there is a role already existing and blows up.
Here is the latest attempt
[Inject]
IServiceProvider services {get;set;}
public async Task Initialize()
{
using (var roleManager = services.GetRequiredService<RoleManager<IdentityRole>>())
{
string proRole = "Pro";
if (!await roleManager.RoleExistsAsync(proRole))
{
var temp = await roleManager.CreateAsync(new IdentityRole { Name = proRole });
}
}
}
And it blows up on the awaited if statement.
Here is the previous code that should work that doesn't.
string proRole = "Pro";
string proClientRole = "ProClient";
if (!await _roleManager.RoleExistsAsync(proRole))
{
var temp = await _roleManager.CreateAsync(new IdentityRole { Name = proRole });
}
which is inside of a method.
I also had it as #{code in the Razor file and after an hour of trying different things there I moved it to a base class because they have been more stable in the past.
It is not the database connection because that is well verified and also because UserManager is called in the same class and it work
I also tried this code (Blazor Role Management Add Role trough UI (Crud)) both suggestions.
This is one bad thing about Blazor for me is it is buggy I never know if it is my bad, or just something wrong with the latest greatest. But I am assuming it is my bad in this case.
Anyway any help would be much appreciated, I am way too many hours on this,
I copy/pasted the same code to the "/" page and it works there.
For some reason it wouldn't work in a component loaded into a component but the standard Role code works as expected in the "/" page.
Most likely I should have restarted my computer as it now works in the original location too.

Is it possible to have a function in a controller act as if the controller has the [ApiController] attribute but it has not?

I have a .net core MVC project that uses AJAX to retrieve data when loading grids.
Today, both the function returning the view and the function returning the data for the grid, is in the same controller. This is not optimal for many reasons. I.e. I would like a Json ProblemResult to be returned if a exception occurs when calling function using AJAX, but when returning a View, I would like the Developer Exception page to be shown if an error occurs.
I could split the functions into different Controllers and annotate one of them with the ApiController attribute, but since the project has several hundreds of controllers it would be a significant task to do so.
What I would like is this:
If context type is application/json: Do model validation and return a “ProblemResult” if a exception occurs, otherwise use the Developers Exception Page to show the error.
Can this be done in a easy way, or do I need to build a middleware and handle it all by myself?
The easy way, meaning, doing this from a function that returns either a view or a type of JSON result would look something like this:
public IActionResult AjaxOrView(CheckModel model)
{
var isAjax = Request.Headers["X-Requested-With"] == "XMLHttpRequest";
var modelStateValid = ModelState.IsValid;
if (isAjax)
{
if (!modelStateValid)
{
return JsonProblemResult();
}
return Json();
}
if (!modelStateValid)
{
// this will throw and the exception page will be shown
throw new Exception();
}
return View();
}

Understanding cakephp3 error handling

I want to create a maintenance Page for my cake website by checking a Database Table for a maintenance flag using a sub-function of my AppController "initilize()" method. If the flag is set, i throw my custom MaintenanceException(Currently containing nothing special):
class MaintenanceException extends Exception{
}
To handle it, I implemented a custom App Exception Renderer:
class AppExceptionRenderer extends ExceptionRenderer {
public function maintenance($error)
{
return "MAINTENANCE";
}
}
I am able to see this maintenance Text on my website if I set my DB flag to true, but I could not find any information in cake's error handling documentation (http://book.cakephp.org/3.0/en/development/errors.html) on how I can actually tell the Exception renderer to render view "maintenance" with Template "infopage".
Can I even us that function using the ExceptionRenderer without a custom error controller? And If not, how should a proper ErrorController implementation look like? I already tried this:
class AppExceptionRenderer extends ExceptionRenderer {
protected function _getController(){
return new ErrorController();
}
public function maintenance($error)
{
return $this->_getController()->maintenanceAction();
}
}
together with:
class ErrorController extends Controller {
public function __construct($request = null, $response = null) {
parent::__construct($request, $response);
if (count(Router::extensions()) &&
!isset($this->RequestHandler)
) {
$this->loadComponent('RequestHandler');
}
$eventManager = $this->eventManager();
if (isset($this->Auth)) {
$eventManager->detach($this->Auth);
}
if (isset($this->Security)) {
$eventManager->detach($this->Security);
}
$this->viewPath = 'Error';
}
public function maintenanceAction(){
return $this->render('maintenance','infopage');
}
}
But this only throws NullPointerExceptions and a fatal error. I am really dissapointed by the cake manual as well, because the code examples there are nowhere close to give me an impression of how anything could be done and what functionality I actually have.
Because I had some more time today, I spent an hour digging into the cake Source and found a solution that works well for me (and is propably the way it should be done, altough the cake documentation does not really give a hint):
Step 1: Override the _template(...)-Method of the ExceptionRenderer in your own class. In my case, I copied the Method of the parent and added the following Code at the beginning of the method:
$isMaintenanceException = $exception instanceof MaintenanceException;
if($isMaintenanceException){
$template = 'maintenance';
return $this->template = $template;
}
This tells our Renderer, that the error Template called "maintentance"(which should be located in Folder: /Error) is the Error Page content it should render.
Step 2: The only thing we have to do now (And its is kinda hacky in my opinion, but proposed by the cake documentation in this exact way) is to set the layout param in our template to the name of the base layout we want to render with. So just add the following code on top of your error template:
$this->layout = "infopage";
The error controller I created is actually not even needed with this approach, and I still don't know how the cake error controller actually works. maybe I will dig into this if I have more time, but for the moment.

Switching MVC view on Post back using strongly typed views/view models

User requests page for Step1, fills out and submits form that contains selected person, so far so good. After validation of ModelState the next viewmodel is constructed properly using the selected person. I then attempt a redirect to action using the newVM but find on entry to Step2 that MVC wipes out the viewmodel attempted to be passed in. I suspect this is due to how MVC attempts to new up and instance based on query string results. I'll put a breakpoint in and check that, but am wondering how does one change a view from a post back with a new view model passed in?
public ActionResult Step1()
{
var vm = new VMStep1();
return View(vm);
}
[HttpPost]
public ActionResult Step1(VMStep1 vm)
{
if (ModelState.IsValid)
{
var newVM = new VMStep2(vm.SelectedPerson);
return RedirectToAction("Step2", newVM);
}
return View(vm);
}
public ActionResult Step2(VMStep2 vm)
{
return View(vm);
}
I can fix this by containing VMStep2 and a partial to Step2 in Step1 view, but that requires hide and seek logic when really I just want user to see Step2.
I don't see why you should want to call RedirectToAction! What it does it the following:
it tells your browser to redirect and like it or not your browser doesn't understand how to handle your object -- what it does understand is JSON. So if you really insist on using return RedirectToAction("Step2", newVM); you should consider a way to serialize your VMStep2 object to JSON and when the browser requests the Redirect, it will be properly passed and created in your action method public ActionResult Step2(VMStep2 vm)
HOWEVER I'd use a much simpler way ---
instead of
return RedirectToAction("Step2", newVM);
I would use
return View("Step2", newVM);
Thanks to everyone for the great input!
Here's what I did...
I created three views MainView, Step1View, Step2View (Step 1 and 2 were partial strong typed views)
I created a MainViewModel that contained VMStep1 and VMStep2
When controller served Step1 the MainViewModel only initialized VMStep1 and set state logic to tell MainView Step1 was to be shown.
When user posted back the MainView containing the MainViewModel, the MainViewModel knew what to do by the answers provided in VMStep1.
VMStep2 was initialized on the post back, and state was set to tell MainView to show Step2. VMStep1 was no longer relevant and was set to null.
User was now able to answer using VMStep2 and all was well.
The key to this working is that some flag tells the view which partial to show, the partial takes a model supporting it's strong type which is initialized at the right time. End result is fast rendering and good state machine progression.

How to create new instance of a view/viewmodel when navigation occurs with Prism

I am trying to control when a new view is created and when an existing view is shown.
This is a very similar scenario as outlined in the "Navigating to Existing Views" section in the Prism documentation, but I can't get it to work fully:
http://msdn.microsoft.com/en-us/library/gg430861(v=pandp.40).aspx
I am finding I can create the view/view model to begin with ok, but I am then unable to create a new instance of it. I.e. I want more than one instance to exist at once.
Here's an example of the view model:
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class DataEntryPageViewModel : INavigationAware, IRegionMemberLifetime
{
private Guid id;
[ImportingConstructor]
public DataEntryPageViewModel()
{
id = Guid.NewGuid();
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
// In actual fact there would be more logic here to determine
// whether this should be shown to the user
return false;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
}
public bool KeepAlive
{
// For the purposes of this example we don't want the view or the viewModel
// to be disposed of.
get { return true; }
}
}
I am navigating to this as follows:
m_RegionManager.RequestNavigate(
"MainRegion",
new Uri("/DataEntryPageView", UriKind.Relative));
So the first time I call the above the view is shown.
The next time I call RequestNavigate the IsNavigationTarget is hit and it returns false. What I then want it to do is to create a new instance but that doesn't happen. I know it's not happening because the constructor does not get hit and the UI does not update to show the new instance of the view.
Any ideas how I can make it create a new instance?
Many thanks,
Paul
Edit
I have noticed that the second time I call RequestNavigate (to request another instance of the same view) the callback reports an error "View already exists in region." It therefore seems that I can have multiple instances of different views in a region, but not multiple instances of the same view. My understand of this isn't great though so I could be wrong.
Why are you not creating the view when you want a new one to be created? It looks to me like you are using MEF.
Use the container to resolve a new instance of your view
Add the new instance of the view to the MainRegion
Then call Navigate and handle the appropriate logic in IsNavigationTarget
You should use the [Export] attribute in your view with a contract name: [Export("DataEntryPageView")].
I have now been able to get this to work, it was because I didn't have
[PartCreationPolicy(CreationPolicy.NonShared)]
on the class declaration of the view. I had it on the ViewModel.
So this is now resulting in the behaviour I expected.
Thanks though to Zabavsky and Alan for your suggestions.