ControllerContext.ParentActionViewContext in asp.net core - asp.net-core

How can I access ParentActionViewContext in Asp.Net Core, I used following commands, but in core they are not available.
ControllerContext.ParentActionViewContext.RouteData.Values["controller"].ToString();, ControllerContext.ParentActionViewContext.ViewBag.Model as MyViewModel
I was not able to find anything regarding these due to scarcity of information on .Net Core.
Thanks in advance.

To get route data, you need to use ControllerContext.ActionDescriptor instead of ControllerContext.ParentActionViewContext now:
ControllerContext.ParentActionViewContext.RouteValues.Values;
Regarding getting Model. Controller class has own properties:
public dynamic ViewBag { get; }
public ViewDataDictionary ViewData { get; set; }
so you may use
var myModel = this.ViewData.Model as MyViewModel;

You cannot find ParentActionViewContext because there are no Child Actions in ASP.Net Core. They have been replaced by View Components.
You can just invoke them and pass any data you want, without going through the request pipeline again (i.e. no model binding, filters or independent http context)
There is a nice introductory article for the topic here

Related

Unable to create a View in ASP.NET Core MVC

I am working on an ASP.NET Core 7.0 MVC app. I have created a data access layer using EF Core 7.0 with a database-first approach. I was trying to create a Razor view through the "AddView" option from the controller for the "Create" process.
However, I am getting this error:
This is how I inject my DbContext:
builder.Services.AddDbContext<NorthwindContext>(options => options.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection")));
I am new to ASP.NET Core. It looks like I have to pass additional options in the Program.cs file. I did a Google search, but couldn't find any help!
If I create the view manually it might work. However, I would like to create it through the scaffolding process.
This is my NorthwindContext code:
After removing the parameterless constructor as per Neil I am getting the new error:
More specifically to my comment, the AddDbContext registers the context class in the asp.net core DI container so it can be provided whenever any class or process wants an instance of the DbContext.
The view generator will want that. However, if the DI container find a parameterless constructor it will use that first, and therefore not use the constructor that passes in the options.
The outcome is a context is provided that does not have the "UseSqlServer" options set.
Hence the error that a database provider has not been configured.
Remove that parameterless constructor from the DbContext and you should be good to go.
The latest error indicates the constructor requires an object of type DbContextOptions.But the injector cannot create the instance.
You could try with the parameterless constructor and configure the options in OnConfiguring method
And the picture you've shown indicates you've seprated Modes from your MVC projects,Make sure you've setted the right startup project(right click on your solution -- Set startup projects) and configrue which projects would contain the migration classes
public class SomeDbContext : DbContext
{
public SomeDbContext()
{
}
public DbSet<SomeEntity> SomeEntity { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("connectionstring", b => b.MigrationsAssembly("MVCProj"));
}
}
Regist it as below:
services.AddDbContext<SomeDbContext>();
If you still got the error,please upload the minimal codes that could reproduce the error

Autofac register IHttpContextAccessor

I use autofac PropertiesAutowired approach (ASP.NET CORE).
What I need is to get current user in class library project. How can I do it? I want something like this
public IHttpContextAccessor ContextAccessor{ get; set; }
and then to use it like
Context.HttpContext.User.Claims.First(i => i.Type == "NameIdentifier"
Is it possible to do or should I use something else for it?
Note: Below only works when registering Autofac with ASP.NET Core as described here or here.
If it is not required to use auto-wiring for properties I'd suggest you do the following
First, register the dependency as singleton (yes, it's not a problem, MS does it too)
builder.RegisterType<HttpContextAccessor>()
.As<IHttpContextAccessor>()
.SingleInstance();
Assuming your class is called MyClass inject it via constructor
public MyClass(IHttpContextAccessor httpContextAccessor)
{
ContextAccessor = httpContextAccessor;
}
Now you are good to go! I am sure you can make it work with property-auto-wiring but I am not familiar with that approach.
As a side-note:
If you want to retrieve the information of the authenticated user, I heard and have read that it is recommended to write something like an ApplicationUser class that wraps the underlying framework logic.
I implemented something similar here that also uses IHttpContextAccessor to retrieve required claims + I am registering the accessor with autofac as well. Only difference is that I am using constructor-injection.
I hope that helps you!

What is the best practices to handle multiple form operation under same action in ASP.NET MVC4?

I have the following scenario in my ASP.NET MVC4 project using Razor Engine:
I have a view with at least 4 different forms.
I would like to handle all form POST under same action mapping.
Actually, the 4 forms post to different Route Mapping, as follow:
POST: /User/FilterRolesInUse/15
POST: /User/RemoveRoles/15
POST: /User/FilterRolesNotInUse/15
POST: /User/AddRoles/15
I would like to know if is it possible to handle all 4 form under the same Route Mapping, something where all form post to /User/Roles/15 and then the controller can distinguish which form was submitted. The concept is something like:
class UserController : Controller {
//
// POST: /User/Roles/
public ActionResult Roles(int? id, object form) {
return DelegateToFormLogic(id, form);
}
}
I just want to know if is it possible because I really want to keep URL consistent.
Any advice or suggestion are welcome.
I do not see any advantage to having a single action that performs multiple functions. In fact it will be confusing to anyone that has to support the code. I would get away from submitting forms and use Ajax methods in your web client (using JQuery ajax) to get the data you need for this view and for update/insert/delete actions. This way you do not have to post back the whole page to perform actions that will probably take place on just portions of the view which will result in a better performing page and a better user experience. Change your controller to a ASP.NET Web API controller and make those methods a REST API that uses consistent URL naming convention and use HTTP verbs to indicate the type of action being performed. You will end up 3 methods that serve the 4 you have now and it could look something like this (they correspond to the same order listed in the question).
GET: /api/Role/15?InUse=True
DELETE: /api/Role/15
GET: /api/Role/15?InUse=False
POST: /api/Role
Your controller would look like this.
class RoleController : ApiController {
public List<Role> Get(int id, boolean InUse) { ... }
public void Delete(int id) { ... }
public void Post(List<Role> roles) { ... }
}
This maintains a clear separation of concerns while also keeping a consistent and understandable URL convention.

asp.net mvc without entity framework

I am learning asp.net mvc and went through a great tutorial that demonstrated it. The tutorial also used Entity Framework.
We have our own data access class which I have to use.
I am a little bit confused as to what I need to do to bridge the gap between our class and MVC framework.
For example, in the tutorial, inside of MovieController.cs file, there is a Edit method, that looks like this:
[HttpPost]
public ActionResult Edit(Movie movie)
{
if (ModelState.IsValid)
{
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
If I don't use the Entity framework, what would it look like? Will I still need to use ModelState.IsValid and save the state like it's done
db.Entry(movie).State = EntityState.Modified;
Please advise. A clearly written example of using asp.net mvc without the use of Entity framework would be great.
What I need to know is what role does state play here and whether it is mandatory to use or is it just a part of how the Entity framework operates.
I would re-write this as:
[HttpPost]
public ActionResult Edit(Movie movie)
{
myDBObject.SaveChanges();
return RedirectToAction("Index");
}
Where myDBObject is my custom database access object.
The examples you see out there where controllers use directly some data access framework such as Entity Framework are bad examples. The whole internet is polluted with such stuff. I can hardly look at it without having my eyes hurt. I consider those as bad practices. Data access should be separated and abstracted in a repository. So for example:
public interface IMoviesRepository
{
Movie Get(int id);
void Save(Movie movie);
}
then you could have some implementation of this interface using plain ADO.NET, EF, NHibernate, a remote web service call, some custom ORM or really whatever:
public class MyCustomFrameworkMoviesRepository: IMoviesRepository
{
...
}
and the controller will take this repository interface as constructor argument:
public class MoviesController: Controller
{
private readonly IMoviesRepository _repository;
public MoviesController(IMoviesRepository repository)
{
_repository = repository;
}
public ActionResult Index(int id)
{
var movie = _repository.Get(id);
return View(movie);
}
[HttpPost]
public ActionResult Index(Movie movie)
{
if (!ModelState.IsValid)
{
return View(movie);
}
_repository.Save(movie);
return RedirectToAction("Success");
}
}
and the last part is to configure your dependency injection framework to pass the correct implementation of the repository into the controller. Now as you can see the way the data is fetched is completely decoupled from the controller logic. It is the way it should be. Always try to avoid the strong coupling between the different layers of your application.
And to answer your question about the State property : this is something completely specific to EF, seeing something like this in a controller is a really pity.
And to bring this even further and improve it you would introduce view models. View models are classes which are specifically designed to meet the requirements of a given view. So for example Movie is a domain model. Domain models should never be directly passed to views. Controller actions should never take domain models as action arguments. You should define view models which will contain only what is required by the given view and then perform the mapping between the view models and the domain models. Frameworks such as AutoMapper make this very simple.
hmm.
MVC and entity framework really have nothing to do with each other; they just work well together.
the if (ModelState.IsValid) validates your view model. If you are not using view objects with validators, it's a little pointless; if you are, then it's quite valuable.
inside the if (ModelState.IsValid) brackets, you would take the post data from your web page (usually a view model) and apply it to the object that will persist it to the database. EF is often used because once it's set up, it's fairly easy to maintain, and a lot less code to write.
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
are both EF-related. These would need to be replaced by your repository class methods and objects.
return RedirectToAction("Index");
is MVC. Upon successful persistence to your data store, return the control to the index page.
return View(movie);
is used to redirect back to the original view, because something failed validation.
You would still check ModelState.IsValid, but otherwise your code would look like what you have.
This assumes that your model has DataAnnotations attributes on it, though, which is what ModelState.IsValid is using to check. Those attributes can be used on any C# class' properties - not just Entity Framework.
You might end up creating specific view models for this purpose.
You need to make some connection between the Movie object (passed in on the http POST) and your database methods (myDBObject).
Maybe you want to say myDBObject.SaveChanges(movie) and assuming your db code knows how to handle the object Movie then you'll be fine.

Silverlight 3 Validation MVVM WCF EF

My application is SL2 reading and writing data through an Entity Framework Model exposed via WCF. We have resisted writing any UI validation due to the exicting new validation controls coming from SL3.
...However after doing a trial update on our project yesterday, we realised that most of the standard practices for attaching validation properties to business objects can't readily be applied when the objects are created from the EF model.
Has anyone had any similiar experiences yet, if so how did you work around this?
Thanks,
Mark
You are correct, you have 2 options.
In your model, or viewmodel, depending on your implementation of MVVM, in the setters for your properties, do some validation there, and throw an exception if there is a problem, then use SL3 ValidatesOnException property in your databinding on the view for each control being validated.
use MetaDataClasses to provide addon functionality to ur existing domain model
[MetadataClass(typeof(MyMetadataClass))]
public partial class MyClass
{
public int MyProperty { get; set; }
}
public class MyMetadataClass
{
[Range(1,100)]
public int MyProperty{ get; set; }
}