MVC Shared partial view with a dropdown and separate controller - asp.net-mvc-5

What I am after is having a partial view that hosts a dropdown list of all available languages in the system. This partial view will be used in many edit templates and will be loaded from a separate controller.
Following the articles and information on the net I have the following implementation:
ViewModel
public class LanguagesViewModel
{
public int SelectedID { get; set; }
public virtual SelectList Languages { get; set; }
public LanguagesViewModel(int selectedID, IEnumerable<Language> languages)
{
SelectedID = selectedID;
Languages = new SelectList(languages, "LanguageId", "Name");
}
}
In the Shared folder I have a file: _LanguageDropDownList.cshtml with
#model XNETProductQuote.Web.Models.LanguagesViewModel
#Html.DropDownListFor(model => model.SelectedID, Model.Languages)
I have a LanguageController that has the following implementation
public ActionResult GetAllLanguages()
{
var languages = service.GetAll();
return PartialView("_LanguageDropDownList", new LanguagesViewModel(1, languages));
}
So the above is meant to load the drop down list in that partial view so I can use it in other templates.
From a template that is loaded from a different controller (ApplicationSetting) I call the partial view using:
#Html.Action("GetAllLanguages", "LanguageController")
This doesn't work. It throws an exception:
The controller for path '/ApplicationSetting/Edit/1' was not found or does not implement IController.
What is the correct implementation for such scenario?
Thanks

In Asp.Net MVC when we make a new controller then 'Controller' postfix is automatically attached to the Controller Name for ex:- in your case if you give 'Language' name to the controller then controller's complete name will be like 'LanguageController',so where ever you want to give controller name you have to use only 'Language' not 'LanguageController' and one of the overloads of #Html.Action() is ControllerName which is only 'Language' and not 'LanguageController' ,So in your problem just change #Html.Action("GetAllLanguages", "LanguageController") with #Html.Action("GetAllLanguages", "Language") and your problem will be solved.

Related

How to use multiple model in Controller Type "MVC5 Controller with View using Entity Framework"

I've created Entire my project with Model from ORACLE and Then Controller with Type "MVC5 Controller with View using Entity Framework".
Now the requirement is to consolidate new model in my existing View, How do i don that ?
I need to know how to add multiple Model in Single Controller/View.
Steps/Screen Shots would be appreciated.
Here are some useful examples and along the lines of what I was going to suggest:
https://www.c-sharpcorner.com/UploadFile/ff2f08/multiple-models-in-single-view-in-mvc/
MVC 5 Multiple Models in a Single View
In short, use a ViewModel class to bundle multiple model classes to send to the view.
A snippet from the accepted answer of the referenced stackoverflow Link:
public class ToPage
{
public WebsiteTheme WebsiteTheme{ get; set; }
public User User { get; set; }
public ToPage() {
websiteTheme = new WebsiteTheme();
user = new User();
}
}
Just use this template to get started.
https://youtu.be/912q3TEF25U

Mvc5 pass model to Layout Page

I have an MVC 5 site with adminlte template. It's work fine. Now I need pass to some data to _layout page. I need pass to _layout page same info as number of alert, number of email, alert list ecc. I read same document about BaseController where do this operation, i.e. read this data and put in a model, or create an abstract model and put this info into. But is not possibile create this model one time (i.e. on user login controller) and share it in all request without re-create it every controller call? Pratically, as a global singleton variabile.
Thanks.
Looks like a good usecase to use a ChildAction which can be called from the layout view.
So start by creating a view model to represent the data
public class AlertVm
{
public int EmailCount { set; get; }
public int NotificationCount { set; get; }
}
Now create an action method which creates an object of this, set the values and pass to a partial view
[ChildActionOnly]
public ActionResult Alerts()
{
var vm = new AlertVm {EmailCount = 4, NotificationCount = 2};
return PartialView(vm);
}
Now your Alerts.cshtml view, which is strongly typed to our view model, you can render whatever you want.
<div>
<p>#Model.EmailCount emails</p>
<p>#Model.NotificationCount notifications</p>
</div>
And this action method can be invoked from the _Layout.cshtml view.
<div>#Html.Action("Alerts", "Home")</div>
With this approach, you do not need worry about the creating a view model for every single action. (Ex : Your about page which does not need a view model usually)
Yeah you can create a base view model & make all the model inherit it
public class MyModel
{
public MyBaseClass BaseClass { get; set; }
}
public abstract class MyBaseClass
{
public virtual string MyName
{
get
{
return "MyBaseClass";
}
}
}
public class MyDerievedClass : MyBaseClass
{
public int MyProperty { get; set; }
public override string MyName
{
get
{
return "MyDerievedClass";
}
}
}
only problem is ..the default CreateModel process doesnt register this deafult view model so global.asax is where you tweek it ..
Here is a good explanation

How to send Model to _Layout.cshtml (I need to send another model to Index view too)

I need to send 2 different Models, one to Index view and another one to _Layout.cshtml, how I can do it?
My HomeController:
[Route("")]
public ActionResult Index()
{
HomeViewModel model = new HomeViewModel();
model.A = _repoA.GetLatest(4);
model.B = _repoB.GetLatest(4);
model.C = _repoC.GetLatest(4);
return View(model);
}
I don't like using ViewBag, ViewData & ..., I'm looking for passing the model in same way as we passing model to Views.
You can place this in your Layout to load a partial each time... Pretty useful for loading in a piece of a dynamic menu or a widget on each page.
Along with this line in your layout you can just do your Index page as you normally would.
#{ Html.RenderAction("_widget", "Home"); }
You'll need to send it along in the ViewBag. I found the best bet was to make an abstract controller:
public abstract class ApplicationController : Controller
{
protected ApplicationController()
{
UserStateViewModel = new UserStateViewModel();
//Modify the UserStateViewModel here.
ViewBag["UserStateViewModel"] = UserStateViewModel;
}
public UserStateViewModel UserStateViewModel { get; set; }
}
Then, have all of your controllers inherit from this abstract controller.
In your _Layout.cshtml (or whatever you called it), you'll need to include the following at the top:
#{
var userState = (UserStateViewModel)ViewBag.UserStateViewModel;
}
Duplicate but refined from the 2nd answer to ASP.NET MVC Razor pass model to layout.

Understanding Asp.Net Identity key points

I am an Asp.net developer but very much new to the Asp.net Identity framework. I have been studying the sample application and followed some tutorials too on Identity but still I am not able to grasp the concept completely. I have very firm grip over Asp.net membership but Identity seems nothing like membership. I will explain what I have done so far.
I am creating a simple application in which I am following code first approach. I have created entity model for User which inherits from IdentityUser and has some extra fields. Below is entity model for User.
public class User : IdentityUser
{
public int? CompanyID { get; set; }
public bool? CanWork { get; set; }
public bool? CanSearch { get; set; }
public Company Company { get; set; }
}
Now in the examples people use the name ApplicationUser but for my own purpose I have used name User. Also there is a method in User or ApplicationUser model which is,
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User> manager)
{
CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
I am unable to understand the purpose of this method. Also from an example I have used the following model for Role,
public class Role : IdentityRole
{
public Role()
{
}
public Role(string roleName, string description)
: base(roleName)
{
this.Description = description;
}
public string Description { get; set; }
}
I understand that an extra field is added but I am unable to understand the purpose of overloaded constructor.
The above mentioned confusions are secondary. My primary confusion is that I am familiar that when I create entity models I use DbSet and DbContext and when I call any entity framework method to access the database, the database is created/drop created whichever scheme I am following.
In Identity which method is responsible for creating the Identity tables in the database? I have a IdentityConfig file in which I declare ApplicationUserManager and ApplicationSignInManager. I have also a Startup file. Previously I had only one Startup file in the App_Start folder and when I run the application and tried to accessed any Identity methods it gave me error and was not creating database. I then made the class as partial and created another partial class with same name at the root and then the exception was gone and tables were created. So Startup class is responsible for creating Identity tables? There are extra columns created automatically in the AspNetUsers like PhoneNumber, PhoneNumberConfirmed, TwoFactorEnabled. I don't need these extra columns. Can I remove these? Can I change the names of the Identity tables that are created?
I know these are very basic questions and not one question at all but if I was unable to find some basic tutorial or example for beginners then it would be very beneficial. What I have found are describing those things which I don't need or making me confuse. I want to understand and have control how Identity should work in my application but till now it seems to me that neither I am grasping it completely and nor being able to make is adjustable to my needs. Its like tutorials and example are teaching me how to make sentences but I am unable to understand the alphabets. :(
First of all you have to define the model - as you're doing - implementing the right interfaces.
Let's say you want to create a user for your application:
public class MyUser : IdentityUser<string, MyUserLogin, MyUserRole, MyUserClaim>
{
public string CompanyName { get; set; }
}
As you can see I've implemented the IdentityUser interface (namespace Microsoft.AspNet.Identity.EntityFramework).
I've specified what type of identifier I want to use for my primary key (string) and included my custom objects to manges login, roles and claims.
Now we can defined the role object:
public class MyRole : IdentityRole<string, MyUserRole>
{
}
Again there's a type and the class I've defined for the management of users belonging to to a role.
public class MyUserRole : IdentityUserRole<string>
{
}
MyUserLogin is going to implement IdentityUserLogin<string>.
MyUserClaim is going to implement IdentityUserClaim<string>.
As you can see each interface need a type for the primary key.
The second step is to create the user store:
public class MyUserStore: UserStore<MyUser, MyRole, string, MyUserLogin, MyUserRole, MyUserClaim>
{
public MyUserStore(MyContext context)
: base(context)
{
}
}
Again we have defined what user, role, login etc etc we want to use.
We need UserStore cause our UserManager is going to need one.
If you're planning to manage roles and associate roles with each user you have to create your RoleStore definition.
public class MyRoleStore : RoleStore<MyRole, string, MyUserRole>
{
public DaufRoleStore(ApplicationDatabaseContext context) : base(context)
{
}
}
Now you can create your UserManager. The UserManager is the real responsible of saving changes to the UserStore.
public class ApplicationUserManager : UserManager<MyUser, string>
{
public ApplicationUserManager(IUserStore<MyUser, string> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new MyUserStore(context.Get<MyContext>()));
manager.UserValidator = new UserValidator<MyUser, string>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
manager.PasswordValidator = new PasswordValidator()
{
RequiredLength = 5,
RequireNonLetterOrDigit = false, // true
// RequireDigit = true,
RequireLowercase = false,
RequireUppercase = false,
};
return (manager);
}
}
This class has a static method which will create a new UserManager for you.
Interesting to note that you can include some validation rules you might need to validate password etc etc.
Last thing is to create or database context.
public class MyContext : IdentityDbContext<MyUser, MyRole, string, MyUserLogin, MyUserRole, MyUserClaim>
{
public MyContext(): base("<your connection string here>")
{
}
public static MyContext Create()
{
return new MyContext();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<MyUser>()
.ToTable("Users");
modelBuilder.Entity<MyRole>()
.ToTable("Roles");
modelBuilder.Entity<MyUserRole>()
.ToTable("UserRoles");
modelBuilder.Entity<MyUserClaim>()
.ToTable("UserClaims");
modelBuilder.Entity<MyUserLogin>()
.ToTable("UserLogins");
}
}
As you can see I've used the model builder to change the names all the tables.
You can define keys or fields type or tables relations here.
This is the place where you're going to attach your custom classes you want to manage in your context:
public DbSet<MyCustomer> Customers{ get; set; }
Again MyContext has a Create method which returns a new context:
public static MyContext Create()
{
return new MyContext();
}
Now you should have a startup class where you're going to bootstrap your stuff:
[assembly: OwinStartup(typeof(ASPNETIdentity2.Startup))]
namespace ASPNETIdentity2
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.CreatePerOwinContext(MyContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
}
}
}
Here you're going to create your database context and your user manager you can use in your application.
Notice the first line:
[assembly: OwinStartup(typeof(ASPNETIdentity2.Startup))]
This is needed cause you're telling your environment that is the startup class which needs to be called at ... startup.
Now in your controllers you can simply refer to your UserManager doing something like this:
HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
How can you create your tables?
In Visual Studio go to TOOLS -> NuGet Packager Manager -> Package Manager Console.
In the window there's a combobox "Default Project". Choose your ASP.NET MVC project.
Run this command:
Enable-Migrations
It will create a file Configuration.cs in a new folder called Migrations.
If you want to create your database you need to open that file and change the AutomaticMigrationsEnabled to true:
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
Again, from Package Manager Console, you can run:
Update-Database
and all your tables will appear in your database. Don't forget your connection string.
You can download this github project to see how everything works.
You can check these two answers with some other info.
The first of the two has got some links to a blog where you can learn all these things.
NOTE:
You have to do all this if you want to customized every single bit of your environment.

Request DTO map to Domain Model

I have the following Domain Model:
public class DaybookEnquiry : Entity
{
public DateTime EnquiryDate { get; set; }
[ForeignKey("EnquiryType")]
public int DaybookEnquiryTypeId { get; set; }
public string AccountNumber { get; set; }
[ForeignKey("User")]
public int UserId { get; set; }
#region Navigation Properties
public virtual User User { get; set; }
public virtual DaybookEnquiryType EnquiryType { get; set; }
public virtual ICollection<DaybookQuoteLine> QuoteLines { get; set; }
#endregion
}
This is inside of a project named DomainModel. Entity is just a base class which my domain models inherit from, it contains an Id field.
I then have other projects inside my solution called ServiceInterface and ServiceModel. ServiceInterface contains all my services for my application and ServiceModel contains my DTO's and routes etc.. I'm trying to follow the guidelines set out here: Physical Project Structure
My EnquiriesService contains a method to create a new enquiry in my database using a repository:
public void Post(CreateEnquiry request)
{
// Not sure what to do here..
// _repository.Insert(request);
}
My CreateEnquiry request looks like so:
[Api("POST a single Enquiry for Daybook.")]
[Route("/enquiries", "POST")]
public class CreateEnquiry : IReturnVoid { }
As you can see, the CreateEnquiry request object is empty. Do I need to add properties to it to match my Domain Model and then use AutoMapper or something similar to map the fields to my Domain Model and pass that into my repository?
The Insert method on my repository looks like so:
public virtual void Insert(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State != EntityState.Detached)
{
dbEntityEntry.State = EntityState.Added;
}
else
{
DbSet.Add(entity);
}
DbContext.SaveChanges();
}
Yes. Your Service request, in this case CreateEnquiry needs to have all the properties you need in order to do whatever it is you want to do!
I've seen two different models for Create vs Update:
Use one request objects called, say, SetEnquiry that has a nullable id field. When null and using the POST HTTP verb, it internally creates a new object. And when not null and using the PATCH HTTP verb, it internally updates an object. You can use ServiceStack's implementation of AbstractValidator<T> to add logic such as if POST then id field needs to be null; and if PATCH then id field cannot be null. This will help ensure your data is always as it needs to be.
Create two request objects -- one for Create and one for Update. The Create doesn't even have an id field, and the Update has one and requires it. You can use the same validation technique used above, except applied to each class independently, so you don't need the conditional check of if this verb do this; if that verb do that.
How you map to your data model is up to you. You can use something like AutoMapper or you can use ServiceStack's built-in TranslateTo and PopulateWith methods. I personally take a middle ground: I created my own object extension methods called MapTo and MapFrom that interally call TranslateTo and PopulateWith respectively. Why did I do this? Because then I control those extensions inside my own namespaces and when I need to do special mappings (like a column name doesn't match up, or one object is more complex than the other, or I simply want to ignore a particular column from one of the objects) I simply overload the MapTo and MapFrom with explicit types, giving it higher specificity than the generic methods.
So back to your question specifically. Assuming you're using the built in TranslateTo your service method might look like this:
public void Post(CreateEnquiry request)
{
_repository.Insert(request.TranslateTo<Enquiry>());
}
One more thing: I generally return the object itself when doing a Create and Update. As fields can change (auto-calculated fields, for example) I like to return the object back to the caller. This is preference and has no real bearing on the answer I'm giving you. Just throwing it out there!

Resources