Stack Exchange
More specific parameter type in the `View` method
One of the most popular books on ASP.NET Core is "Pro ASP.NET Core 3" by Adam Freeman.
In chapters 7-11, he builds an example application, SportsStore.
The Index method of the HomeController shows a list of products:

Here's the Index method:
public ViewResult Index(int productPage = 1)
   => View(new ProductsListViewModel {
       Products = repository.Products
           .OrderBy(p => p.ProductID)
           .Skip((productPage - 1) * PageSize)
           .Take(PageSize),
       PagingInfo = new PagingInfo {
           CurrentPage = productPage,
           ItemsPerPage = PageSize,
           TotalItems = repository.Products.Count()
       }
   });

The view file that corresponds to this method is Views\Home\Index.cshtml. This file has the following line at the top:
@model ProductsListViewModel

So the view is expecting an object of type ProductsListViewModel. However, in Visual Studio, IntelliSense shows View as expecting an argument of type object:

I'm surprised that View here isn't shown to expect an object of type ProductsListViewModel. Since it's setup to accept an argument of type object, we can actually pass in some nonsensical value:
public ViewResult Index(string category, int productPage = 1) =>
    View(10);

and the project will still compile!
Is there a way to set things up so that View actually only accepts the model type specified in the view file? I.e. in this case, set things up so that View only accepts ProductsListViewModel?
Thanks!

By using generic, I did the following.
   //This is the Base class for every model must inherit.
   public class EntityModel
    {
        public int ID { get; set; }
    }

 //Model / view model must inherit from   EntityModel
 public class EmployeeModel : EntityModel
{
    public string Name { get; set; }
}

Create a new ViewController which accepts only the EntityModel or its derived class.
Mark the View and its overloaded method obsolete so that only the entity Model calls as a parameter can only be used. Also if anyone uses it show restrict them for using it. Therefore throw error.
public class ViewController<T> : Controller where T: EntityModel
{
    [Obsolete]
    public override ViewResult View()
    {
        return base.View(); 
    }

    [Obsolete]
    public override ViewResult View(object model)
    {
        throw new Exception("Use view method which accepts EntityModel");
    }

    [Obsolete]
    public override ViewResult View(string viewName)
    {
        throw new Exception("Use view method which accepts EntityModel");
    }

    [Obsolete]
    public override ViewResult View(string viewName, object model)
    {
        throw new Exception("Use view method which accepts EntityModel");
    }

    public new ViewResult View(T model)
    {
        return base.View(model);
    }
}

Use the newly created ViewController in your Home Controller.
public class HomeController : ViewController<EmployeeModel>
{

    public IActionResult Index()
    {

        EmployeeModel emp = new EmployeeModel();
        emp.ID = 1;
        emp.Name = "Satish Pai";
        return View(emp);
    }
}


This is an interesting approach! Thanks Satish!

How's that going to work if I have different view models for different actions within the same controller? This is likely the way. For example, you might have a summary view model for the index to display list of summarized items, create item view model that usually doesn't have the ID property, update item view model, on the other hand, that usuallay has the key, etc.

The entity model is a base class for all the viewmodel. So then developer who is using the viewcontroller is restricted to give only the viewmodel of inherited from entity model. If there is any other requirement we need make change in generic constraint. Hope i answered your question.

@SatishPai: But I can still pass the wrong models to the view, if I want to. Let's say ViewModel1 and ViewModel2 both inherit from EntityModel, and the Index view expects ViewModel1. I can still pass ViewModel2 to that view.... You are not going to declare only the base EntityModel on every view are you?

I don't think there is a way to catch any wrong view models got passed into views at compile time!
The problem
The view is strongly typed with the view model you declare on the top so it knows what model is coming in, but the controller doesn't know which view you want it to return to...
By default, yes the controller is going to return to a view that has the same name as the method, but you can change that default, and you can even pass the name of the view as string parameter to one of the View() overloads:
public IActionResult Index(string category, int page = 1)
{
    ...
    return View("OutOfStock", vm);
}

Now Visual Studio doesn't know which view model you want the controller to build and pass to the view. In fact, Visual Studio doesn't even know what view I want to return. Even after I put "OutOfStock" as the view name, Visual Studio doesn't know whether the view even exists or not...

Using Generic
@Satish's solution is indeed interesting but it assumes you are only working with 1 single view model for a single controller, which normally isn't the case. Usually you will have different view models for different actions.
If Generic were the way to go, I would suggest to put it on the action, rather on the controller:
public abstract class BaseController : Controller
{
    public ViewResult View<T>(T viewModel)  where T : new()
    {
        return View(viewModel);
    }
}

Then you can use it like this in the controller:
public class ProductController : BaseController
{
    public IActionResult Index(string category, int page = 1)
    {
        var vm = new ProductListViewModel
        {
            ...
        };
    
        return View<ProductListViewModel>(vm);
        
        // This would give you the compile time error!
        // return View<ProductListViewModel>(10);
    }
}

But why? What's the point of doing this? You, as the developer, have to know ProductListViewModel is the right view model to pass anyway. Putting something like this in place would be only helpful if there is a junior or new hire who's working on your code and doesn't bother to check the view model the returned view is asking for?

Maybe?
Now I know a tool like Resharper might be able to help and catch the mismatch at compile time.
Also writing unit tests on what the methods in the controller return might be helpful?

Thank you for the thoughtful answer David!
