How to remove ViewModel Required before sending it? - c#

I have a view model with a "field" that is required.
public class MyViewModel
{
[Required(ErrorMessageResourceType = typeof(Global), ErrorMessageResourceName = "Required")]
public string Code { get; set; }
}
And in one of my controllers, I'm return that view model.
But, depending on some parameters, I want to remove the required.
public ActionResult Create()
{
var model = new MyViewModel();
if(something){
model.SomeThingToRemoveTheRequiredFromCode();
}
return View(model);
}
How can I remove the required from the view model in the situation where I just created the view model?

Here's an approach. Create a new model without the Required attribute
public class MyViewModelToo
{
public string Code { get; set; }
}
then in the condition, return the view using that view model
public ActionResult Create()
{
var model = new MyViewModel();
if(something){
var modelToo = new MyViewModelToo();
return View(modelToo);
}
return View(model);
}

you can remove it from model-state dictionary like this
if(something){
Modelstate.Remove("Code")
}

If you have only one field you can use this
public ActionResult Create()
{
var nmodel= new MyViewModel().fieldname;
if(something){
return View(nmodel);
}
return View(model);
}
Or you can use #using System.Web.ModelBinding; in your class
ModelState.Remove("Code");

Related

How to pass a list of ViewModels to a View?

I am quite new to C# and asp.net mvc and I have been trying to find an answer to my question here and in other foras but have not succeeded. However if this question has been asked and answered before then I apologize and could you please link to that post.
I am trying to create a treeview where I pass a list of ViewModels to my View.
I use code-first approach and have added a migration between my model and the database.
My problem is how to pass a list of objects of the ViewModel to the View?
I can pass a list of objects of the model from the controller but how to pass a list of objects of the ViewModel? Is that possible?
Maybe there is a simple solution to this that I have not found yet and maybe I am doing this all wrong. Anyway I really need some help.
public class MyClass
{
public int Id { get; set; }
public int ParentId { get; set; }
public string Name { get; set; }
}
public class MyClassViewModel
{
public MyClass Parent { get; set; }
public List<MyClass> Children
{
get { return GetChildren(); }
}
public List<MyClass> GetChildren()
{
var listOfChildren = new List<MyClass>().Where(c => c.ParentId ==
Parent.Id).ToList();
return listOfChildren;
}
}
public ActionResult CreateTree()
{
var viewModel = new MyClassViewModel();
//This only returns one instance of an object, how to return a list?
return View("CreateTree", viewModel);
}
It is very simple, you just pass the list of your view model to the view:
[HttpGet()]
public IActionResult CreateTree()
{
List<MyViewModel> viewModelList = MyViewModel.GetList();
return View("CreateTree", viewModelList);
}
On the view, you set the expected type for the model via the #model directive.
#model List<MyViewModel>
#{
//stuff
}
Now you can just iterate through your list of viewmodel.
#foreach (MyViewModel item in Model)
{
//stuff
}
You could create a class, containing a list of your ViewModels
public class ModelWithListOfViewModels
{
public List<ViewModel> ViewModels { get; set; }
}
Add your ViewModels to the list in the controller
public ModelWithListOfViewModels model { get; set; }
[HttpGet()]
public ActionResult FillList()
{
model = new ModelWithListOfViewModels();
//Here you fill the list with the ViewModels you want to pass to the View
model.ViewModels.Add(/** ViewModel here **/);
return View("CreateTree", model);
}
Then simply loop over the list to get your model in the View
#model ModelWithListOfViewModels
#foreach (var vm in Model.ViewModels)
{
//use vm to get access to a ViewModel added in the list
}

Cannot create post my values

I want to use create, but when I post my values don´t register in my database also in my view too.
Model:
public class WebPages
{
[Key]
public DateTime DomainStart { get; set; }
public DateTime DomainExp { get; set; }
}
ViewModel:
public class WebPagesViewModel
{
public DateTime DomainStart { get; set; }
public DateTime DomainExp { get; set; }
}
Post Controller:
[HttpPost]
public async Task<ActionResult>Create([Bind(Include = "DomainName,DomainExp")] WebPagesViewModel model)
{
if (ModelState.IsValid)
{
model.WC();
await db.SaveChangesAsync();
return RedirectToAction("Index", "WebPages");
}
return View(model);
}
Extension method of my post:
public static WebPagesViewModel WC(this WebPagesViewModel model)
{
var wb= new WebPages
{
DomainStart = model.DomainStart,
DomainExp = model.DomainExp,
};
db.WebPagesList.Add(wb);
db.SaveChangesAsync();
return model;
}
So try catch pass, and I get a success post, but values don´t save on database, what I´m doing wrong?
Thankyou in advance!
[HttpPost]
public async Task<ActionResult>. Create([Bind(Include = "DomainName,DomainExp,DomainEmails,DomainUsers,DomainPasswords,ClientsName")]
Change your post method to
[HttpPost]
public async Task<ActionResult> Create([Bind(Include = "DomainName,DomainExp,DomainEmails,DomainUsers,DomainPasswords,ClientsName")]
//model.WebPagesCreate();
pass parameter to the above method
if you want to see error
db.SaveChangesAsync()
change to
db.SaveChanges()
And also check bind values are correctly coming from the view
Add this to view model
public WebPagesViewModel()
{
AvalilableClients = new List<SelectListItem>();
}
public List<SelectListItem> AvalilableClients { get; set; }
Add your client list to Model
foreach (var client in Clients )
{
model.WebPagesViewModel.Clients .Add(item: new SelectListItem()
{
Text = dept.DepartmentName,
Value = dept.DepartmentId.ToString()
});
}
Then Pass model to View Then populate the view drop down using Html Healper
#Html.DropDownListFor(model => model.SelectedClient, Model.AvalilableClients , new { #class = "form-control" })
Finally I solve it, the problem was that my datetime is not setted correctly in my extension method, so I change DomainStart = model.DomainStart to DomainStart = Datetime.now

Passing more multiple queries in a View ASP.NET

In my Repository class I have this two queries that I want it to appear in just one view:
public ClassXXXX GetxxxoList(string Name)
{
return context.ClassXXXX.Where(v => v.Name == Name).Single();
}
And the second query in Repository class I have:
public IEnumerable<ClassXXXX> List()
{
return context.ClassXXXX.ToList();
}
Then in my view I am doing this:
#model IEnumerable<Namespace.Models.ClassXXXX>
#model Namespace.Models.ClassXXXX
To return the two queries in my view respectively.
But ASP.NET throws exception on using #model twice in just one view.
instead of:
#model IEnumerable<Namespace.Models.ClassXXXX>
#model Namespace.Models.ClassXXXX
You can create an ViewModel class, that contains all your needed data:
public class YourContextViewModel
{
public List<Person> Person { get; set; }
public string UserName{get;set;}
...
}
It's a good idea to create an ViewModel object to populate your views.
I would suggest:
Create a new model that encapsulates both models. Create the model ModelXXXX in the Models namespace
public class ModelXXXX
{
public ModelXXXX(ClassXXXX singleXXXX, List<SingleXXXX> listXXXX)
{
SingleXXXX = singleXXXX;
ListXXXX = listXXXX;
}
public ClassXXXX SingleXXXX { get; set; };
public IList<ClassXXXX> ListXXXX { get; set; }
}
Then in the controller you would have something like:
public virtual ActionResult Index()
{
[...]
string name = "name";
ModelXXXX model = new ModelXXXX(GetxxxoList(name), List());
return View("..Views/Index.cshtml", model)
}
And finally in the view you would have:
#model Namespace.Models.ModelXXXX
[...]
#Model.SingleXXXX
#Model.ListXXXX
The first one (#Model.SingleXXXX) will have the value of #model Namespace.Models.ClassXXXX
And the second one (#Model.SingleXXXX) will have the value of #model IEnumerable

ASP.NET MVC Passing action parameter to the view

Let's say that I have a Action method like this:
public ActionResult Page(int? id)
{
}
The question is, how can I read 'id' parameter in View?
Your code won't build successfully, until you return a view like this
public ActionResult Page(int? id)
{
return View();
}
and because you want to return id to your view you can do
Simple object
public ActionResult Page(int? id)
{
return View(id);
}
Just remember to accept the new value in your view, by dong the following at the top (very first line)
#model int?
ViewModel approach
public class MyViewModel
{
public int? Id { get; set; }
//Other properties here
}
public ActionResult Page(int? id)
{
var myViewModel = new MyViewModel()
{
Id = id
};
return View(myViewModel);
}
and then in your view
#model MyViewModel
You can access parameters from Request in view as below
Request.Params["id"]

Pass a viewModel to the layout

I have this viewmodel that has some properties and stuff that i would like to apply
to the layoutpage:
public class BasicViewModel
{
public Page Page { get; set; }
public List<Settings> Settings { get; set; }
}
From other threads here have i understood that this is possible but i dont really understand how.
From what I understand I somehow need to modify a controller and this is where I get confused. How do I know what controller that has to be modified and how?
Any help appreciated.
In controller, Prepare an action like
public ActionResult BasicViewModelDemo
{
BasicViewModel obj=new BasicViewModel()
// assign properties
return View(obj);
}
and view write some jquery. (Here i am using knockout to make view model)
<script>
var model='#Html.Raw(Json.Encode(Model))';
var viewmodel = ko.mapping.fromJSON(model);
</script>
Here goes my solution -
Lets say you have a model of this way -
public class BasicViewModel
{
public Page Page { get; set; }
public List<Settings> Settings { get; set; }
}
public class Page
{
public string PageName { get; set; }
}
public class Settings
{
public string SettingName { get; set; }
}
Then in the controller you should initiate the model in this way -
public class HomeController : Controller
{
BasicViewModel model;
public HomeController()
{
model = new BasicViewModel();
model.Page = new Page();
model.Settings = new List<Settings>();
}
public ActionResult Index()
{
model.Page.PageName = "My Page";
ViewBag.LayoutModel = model;
return View();
}
}
So basically we used Constructor to initiate the model and then we assign proper values in the controller action.
Then in the Layout, we can use the Model property as shown below -
<div> #ViewBag.LayoutModel.Page.PageName </div>

Categories