My problem is this: I have created a view in which I want to be able to remove and add new identity roles. For that I created two forms that call two different actions. I have created a big model which consists of smaller models which are bound by the forms to the actions. Everything works as intended, models get bound properly, data is there and proper actions are executed as they should.
Don't get me wrong, I understand those are separate forms and I know they will never show validation messages both at the same time because only one form can be posted at a time. The problem is that when I click submit on the CreateNewRole form, the validation message is there, but when I click submit on the RemoveRoles action, I don't get any validation messages and no validation classes are applied to the html elements, there is the usual "field-validation-valid" and no "field-validation-error" class in it while its perfectly present in CreateNewRole.
Why does validation work on the first form but not on the second form? I cant find any difference in how i made those two forms, am i not noticing something?
When I debug modelstate of the RemoveRoles action, the error is there, but somehow the view isn't getting informed of it.
View
#model Models.ViewModels.RolePanelViewModel
#using Extensions
<h2>Role Panel</h2>
<article>
<div class="admin-panel-flex-container">
<div class="form-container">
#using (Html.BeginForm("CreateNewRole", "Administrator"))
{
<div class="form-group">
#Html.LabelFor(l => l.NewRoleRolePanelViewModel.NewIdentityRole.Name)
#Html.TextBoxFor(t => t.NewRoleRolePanelViewModel.NewIdentityRole.Name)
#Html.ValidationMessageFor(t => t.NewRoleRolePanelViewModel.NewIdentityRole.Name)
<button type="submit">Dodaj role</button>
</div>
}
</div>
<div class="form-container">
#using (Html.BeginForm("RemoveRoles", "Administrator"))
{
<div class="form-group">
#Html.LabelFor(l => l.ListRolePanelViewModel.SelectedIdentityRoles)
#Html.ListBoxFor(l => l.ListRolePanelViewModel.SelectedIdentityRoles, #Model.ListRolePanelViewModel.IdentityRolesSelectListItems)
#Html.ValidationMessageFor(t => t.ListRolePanelViewModel.SelectedIdentityRoles)
<button type="submit">Skasuj wybrane</button>
</div>
}
</div>
</div>
</article>
Models
public class RolePanelViewModel
{
public ListRolePanelViewModel ListRolePanelViewModel { get; set; }
public NewRoleRolePanelViewModel NewRoleRolePanelViewModel { get; set; }
}
public class ListRolePanelViewModel
{
public List<IdentityRoleDTO> IdentityRoles { get; set; }
public List<SelectListItem> IdentityRolesSelectListItems { get; set; }
[Required(ErrorMessage = "Należy wybrać przynajmniej jedną pozycję z listy")]
public List<string> SelectedIdentityRoles { get; set; }
}
public class NewRoleRolePanelViewModel
{
public IdentityRoleDTO NewIdentityRole { get; set; }
}
public class IdentityRoleDTO
{
public string Id { get; set; }
[Required(ErrorMessage = "Nowa rola musi mieć nazwę")]
[MinLength(5)]
public string Name { get; set; }
public List<IdentityUserRole> Users { get; set; }
}
Actions
public ActionResult OpenRolePanel()
{
var roles = _context.Roles.ToList();
var viewModel = new RolePanelViewModel
{
ListRolePanelViewModel = new ListRolePanelViewModel
{
IdentityRolesSelectListItems = GetSelectListItems(roles,
(a) => new SelectListItem {Value = a.Id.ToString(), Selected = false, Text = a.Name})
},
NewRoleRolePanelViewModel = new NewRoleRolePanelViewModel()
};
return View("RolePanel", viewModel);
}
[HttpPost]
public async Task<ActionResult> CreateNewRole(NewRoleRolePanelViewModel newRoleRolePanelViewModel)
{
if(!ModelState.IsValid)
{
var roles = _context.Roles.ToList();
var viewModel = new RolePanelViewModel
{
ListRolePanelViewModel = new ListRolePanelViewModel
{
IdentityRolesSelectListItems = GetSelectListItems(roles,
(a) => new SelectListItem { Value = a.Id.ToString(), Selected = false, Text = a.Name })
},
NewRoleRolePanelViewModel = newRoleRolePanelViewModel
};
return View("RolePanel", viewModel);
}
var roleStore = new RoleStore<IdentityRole>(new ApplicationDbContext());
var roleManager = new RoleManager<IdentityRole>(roleStore);
await roleManager.CreateAsync(new IdentityRole(newRoleRolePanelViewModel.NewIdentityRole.Name));
return View("RolePanel");
}
[HttpPost]
public ActionResult RemoveRoles(ListRolePanelViewModel listRolePanelViewModel)
{
if (!ModelState.IsValid)
{
var roles = _context.Roles.ToList();
var viewModel = new RolePanelViewModel
{
ListRolePanelViewModel = listRolePanelViewModel,
NewRoleRolePanelViewModel = new NewRoleRolePanelViewModel()
};
viewModel.ListRolePanelViewModel.IdentityRolesSelectListItems = GetSelectListItems(roles,
(a) => new SelectListItem {Value = a.Id.ToString(), Selected = false, Text = a.Name});
return View("RolePanel", viewModel);
}
return View("RolePanel");
}
Custom method that may be needed if you want to run the code
private List<SelectListItem> GetSelectListItems<T>(List<T> dbSetResult, Func<T,SelectListItem> Func)
{
var result = new List<SelectListItem>();
foreach (var item in dbSetResult)
{
result.Add(Func(item));
}
return result;
}
Related
This is done by adding a view from my controller and selecting my dto as template
My DTO
public class Company_DTO
{
public long ID_Company { get; set; }
public string ESTATE_Company { get; set; }
}
MyController
public ActionResult UpdateCompany()
{
ViewBag.ListOfCompanies = DependencyFactory.Resolve<ICompanyBusiness>().GetCompany(); // this return a List<int> and following what I read for viewbag this should be right.
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UpdateCompany([Bind]Company_DTO company_DTO)
{
try
{
//code
}
catch
{
return View();
}
}
View
<div class="form-group">
#Html.DropDownListFor(model => model.ID_Company , ViewBag.ListOfCompanies) // Here I get an error on my #Html that my dto does nothave a list.
</div>
I want the selected item to be ID_Company, but here it seems to be trying to add the whole list when I just want the selected item, I cant find any documentation or question that can solve my issue.
I Cant EDIT the DTO.
Thanks for any help and hope I am being clear enough.
This should solve your problem:
View
<div class="form-group">
#Html.DropDownListFor(model => model.ID_Company, new SelectList(ViewBag.Accounts, "ID_Company", "ESTATE_Company"))
</div>
Supposing your view is strongly typed (#model Company_DTO).
Hope this helps
consider the following example:
public class HomeController : Controller
{
private List<SelectListItem> items = new List<SelectListItem>()
{
new SelectListItem() { Text = "Zero", Value = "0"},
new SelectListItem() { Text = "One", Value = "1"},
new SelectListItem() { Text = "Two", Value = "2"}
};
public ActionResult Index()
{
ViewBag.Items = items;
return View(new Boo() { Id = 1, Name = "Boo name"});
}
}
public class Boo
{
public int Id { get; set; }
public string Name { get; set; }
}
the view:
#model WebApi.Controllers.Boo
#Html.DropDownListFor(x=>x.Id, (IEnumerable<SelectListItem>) ViewBag.Items)
so, ViewBag.ListOfCompanies should contain IEnumerable. Each SelectListItem has Text and Value property , you need to assign ESTATE_Company and ID_Company respectively. something like this:
var companiesList = //get companies list
ViewBag.ListOfCompanies = companiesList.Select(x => new SelectListItem() {Text = x.ESTATE_Company, Value = x.ID_Company.ToString()});
....
#Html.DropDownListFor(x=>x.ID_Company, ViewBag.Items as IEnumerable<SelectListItem>)
EDIT: I am trying to add a comment to a post in my mvc application but my action does not seem to work. When I reach the Action I want to pass on an Id from a Post (the Id from the table/model FormalBlog) but the newPost.Post = model.Post is null and when the action reaches the db.SaveChanges it throws an System.Data.Entity.Validation.DbEntityValidationException.
Below is my action and my PostIndexViewModel:
public ActionResult Comment(PostIndexViewModel model, FormalBlog Post)
{
var userName = User.Identity.Name;
var author = db.Users.SingleOrDefault(x => x.UserName == userName);
Comment newPost = new Comment();
newPost.Author = author;
newPost.Text = model.Text;
newPost.Post = model.Post;
db.Comments.Add(newPost);
db.SaveChanges();
return RedirectToAction("ShowBlogs", "Blog");
}
}
public class PostIndexViewModel
{
public string Id { get; set; }
public ICollection<FormalBlog> FormalBlogs { get; set; }
public FormalBlog NewFormalBlog { get; set; } = new FormalBlog();
public Category NewCategory { get; set; } = new Category();
public ICollection<Category> Categories { get; set; }
public List<SelectListItem> SelectedCategories { get; set; }
public int[] CategoryIds { get; set; }
public Category CategoryN { get; set; }
public ICollection<Meeting> Meetings { get; set; } //testrad
// public int Id { get; set; }
public string Text { get; set; }
public ApplicationUser Author { get; set; }
public Comment NewComment { get; set; }
public FormalBlog Post { get; set; }
}
and here is the code for my view:
#model XP_Scrum_Grupp2.Controllers.PostIndexViewModel
#using (Html.BeginForm("Comment", "Blog", new { formal = Model }, FormMethod.Post, new { id = Model.Id }))
{
<div class="comment-form-container">
<form class="comment-form" data-action="#Url.Action("Comment", "Blog")">
#Html.HiddenFor(m => m.Id)
<div>#Html.DisplayFor(m => m.Author)</div>
<div>
<div>#Html.LabelFor(m => m.Text)</div>
#Html.TextAreaFor(m => m.Text, new { Class = "comment-text", rows = "3", cols = "50" })
</div>
<div class="comment-result" style="display: none;">
<span class="comment-result-text">An error occurred</span>
</div>
<div>
<button type="submit" class="comment-form-submit">Submit comment</button>
</div>
</form>
</div>
}
Your view does not assign any value to model.NewComment. So when you access model.NewComment.Text it will throw Null reference exception since model.NewComment is null.
You assign new text to model's Test property. So you should use model.Text instead of model.NewComment.Text
public ActionResult Comment(PostIndexViewModel model)
{
var userName = User.Identity.Name;
var author = db.Users.SingleOrDefault(x => x.UserName == userName);
Comment newPost = new Comment();
newPost.Author = author;
newPost.Text = model.Text;
newPost.Post = model.Post;
db.Comments.Add(newPost);
db.SaveChanges();
return RedirectToAction("ShowBlogs", "Blog");
}
You are not posting the any data as model.NewComment.Text so the error occures because of NewComment object is null.
#Html.TextAreaFor(m => m.Text, new { Class = "comment-text", rows = "3", cols = "50" })
So, try to change it;
newPost.Text = model.NewComment.Text;
to
newPost.Text = model.Text;
I have a problem with an application using ASP.NET MVC 4, I'm trying to show in a view to create an entity called CompositePiece, a List of items (which are CompositePieces too) from my database, then, the user could select one or more of them, and the items selected would be in a collection in the 'father' CompositePiece, at first, my class CompositePiece:
namespace Garbi.Models{
public class CompositePiece
{
[Key]
public int CompositePieceId { get; set; }
[Required(ErrorMessage = "Introduzca un nombre para la pieza")]
[Display(Name = "Nombre de la pieza")]
public string CompositePieceName { get; set; }
public virtual ICollection<CompositePiece> Components { get; set; }
public int ProcessId { get; set; }
public int LevelOfHierarchy { get; set; }
public CompositePiece(PieceModel model)
{
this.Components = new List<CompositePiece>();
this.CompositePieceName = model.PieceModelName;
LevelOfHierarchy = 0;
}
public CompositePiece()
{
this.Components = new List<CompositePiece>();
LevelOfHierarchy = 0;
}
public CreateOrEditCompositePieceViewModel ToCreateOrEditCompositePieceViewModel(string processName)
{
return new CreateOrEditCompositePieceViewModel
{
CompositePieceName = this.CompositePieceName,
ProcessId = this.ProcessId,
ProcessName = processName
};
}
}
}
I have created a ViewModel to pass the data to a view, the ViewModel is:
namespace Garbi.ViewModels.CompositePieces
{
public class CreateOrEditCompositePieceViewModel
{
[Required(ErrorMessage = "Introduzca un nombre para la pieza")]
[Display(Name = "Nombre de la pieza")]
public string CompositePieceName { get; set; }
public virtual IEnumerable<SelectListItem> Components { get; set; }
public string[] SelectedComponentsId { get; set; }
public int ProcessId { get; set; }
public string ProcessName { get; set; }
public int LevelOfHierarchy { get; set; }
public void AddComponentsList(IEnumerable<CompositePiece> dataProvider, CompositePiece fatherPiece)
{
List<SelectListItem> auxList = new List<SelectListItem>();
foreach (CompositePiece piece in dataProvider)
{
SelectListItem item = new SelectListItem
{
Text=piece.CompositePieceName,
Value = piece.CompositePieceId.ToString(),
Selected = fatherPiece.Components.Contains(piece)
};
auxList.Add(item);
}
Components = new List<SelectListItem>(auxList);
}
public CompositePiece ToCompositePiece()
{
return new CompositePiece
{
CompositePieceName = this.CompositePieceName,
LevelOfHierarchy = this.LevelOfHierarchy,
ProcessId = this.ProcessId
};
}
}
}
Mi View is:
#model Garbi.ViewModels.CompositePieces.CreateOrEditCompositePieceViewModel
#{
ViewBag.Title = "Crear pieza compuesta";
}
<div class="advertise">Crear pieza compuesta para #Model.ProcessName</div>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Nueva pieza compuesta</legend>
<div class="editor-label">
#Html.LabelFor(model => model.CompositePieceName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CompositePieceName)
#Html.ValidationMessageFor(model => model.CompositePieceName)
</div>
<div class="editor-field">
#foreach (var item in Model.Components)
{
<div class="checkbox">
#Html.CheckBoxFor(i => item.Selected, item.Value)
#Html.HiddenFor(i => item.Value)
#item.Text
#Html.HiddenFor(i => item)
</div>
}
</div>
#Html.HiddenFor(model => model.Components)
#Html.HiddenFor(model => model.LevelOfHierarchy)
#Html.HiddenFor(model => model.ProcessId)
#Html.HiddenFor(model => model.ProcessName)
<p>
<input type="submit" value="Crear" />
</p>
</fieldset>
<div class="back">
#Html.NavLink("Process_"+#Model.ProcessId, "Page1", "Volver")
</div>
}
And at last, I want to show you the methods of my controller, they are:
public ActionResult ComposePieces(int processId)
{
context = new EFDbContext();
Process process = context.ProcessesPaginable.FindEntityById(processId);
CreateOrEditCompositePieceViewModel model = new CreateOrEditCompositePieceViewModel
{
ProcessId = process.ProcessId,
ProcessName = process.ProcessName,
LevelOfHierarchy = 0
};
IEnumerable<CompositePiece> totalPieces = context.CompositePiecesPaginable.FindAllCompositePiecesOfAProcess(processId).Where(p => p.LevelOfHierarchy == 0);
model.AddComponentsList(totalPieces, model.ToCompositePiece());
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ComposePieces(CreateOrEditCompositePieceViewModel model)
{
context = new EFDbContext();
CompositePiece compositePieceToAdd = model.ToCompositePiece();
CompositePiece aux;
[...]
}
My problem comes when I call the view, I can see perfectly the collection of items, each of them with its checkbox, but when I check some of them, put the CompositePiece's name and click at Submit button, I recover the new CreateOrEditCompositePieceViewModel with its new name, but my attribute Components is empty. I think I am having a mistake of base, but I don't know where is the error, and why I have this problem.
Thank you for your time and sorry for my bad english.
I also have the same Problem as you do.
When I get the postback, the Navigation properties are not returning, even thought I select them on the form, or hid them.
I think this Problem has to do with the Attribute being virtual, and by so it uses lazy loading.
One Thing that I tried that showed promising, but still did^'t get the Job done is if you add the:
#Html.HiddenFor(model => Model.Components);
Before your foreach Loop.
What happens is that when you look on you postback, you will find the components there, it won't be null anymore, but still the list will be empty, but I think the solution is on this direction.
Anyways, enough of this.
I'm about to do a way around this that should work.
What you do, you create a viewmodel
with your class
plus list of each of the virtual lists
something like this:
public class MyViewModel
{
public MyModelView(CompositePiece cp)
{
CompositePiece = cp;
Components = cp.Components.ToList();
}
public CompositePiece CompositePiece { get; set; }
public List<Component> Components { get; set; }
}
I just saw that on your class you create a list of itself, you probably shouldn't do that.
That's not how you create linked lists in C#
So, if instead you do like this example, you will create an instance of you virtual lists, and this should solve the Problem.
Good luck.
I am new in mvc and i want to bind dropdownlist in MVC 3.0. My Code is given below
tables
tbl_Modules
------------------
Module_Id
ModuleName
ModuleDescription
tbl_DocumentTypes
-------------------
Document_Id
DocumentName
DocumentDescription
Module_Id
I want to create a form to add document type and in the form I want a dropdownlist with Module_Id as value, ModuleName as text.
public class DocumetRepository
{
InwardManagementEntities db = new InwardManagementEntities();
public IQueryable<tbl_DocumentTypes> FindAllDocumentTypes()
{
return db.tbl_DocumentTypes;
}
}
public class DocumentTypeViewModel
{
ModuleRepository _modulerepository = new ModuleRepository();
public tbl_DocumentTypes Document { get; private set; }
public SelectList Modules { get; private set; }
public DocumentTypeViewModel(tbl_DocumentTypes document)
{
Document = document;
//var _modules = _modulerepository.FindAllModules().Select(d => new {Module_Id= SqlFunctions.StringConvert((double?)d.Module_Id), Text = d.ModuleName });
var _modules = _modulerepository.FindAllModules().Select(d => new SelectListItem() {Value= SqlFunctions.StringConvert((double?)d.Module_Id), Text = d.ModuleName });
Modules = new SelectList(_modules, Document.Module_Id);
}
}
Controller:
public ActionResult AddDocument()
{
tbl_DocumentTypes _document = new tbl_DocumentTypes();
return View(new DocumentTypeViewModel(_document));
}
View:
<div class="editor-label">Module</div>
<div class="editor-field">
#Html.DropDownList("Document.Module_Id", Model.Modules.ToList())
#Html.ValidationMessageFor(model => model.Document.Module_Id)
</div>
But in dropdownlist I'm getting System.Web.Mvc.SelectListItem. Please help.
Change the Module property of your DocumentTypeViewModel to type of IEnumerable<SelectListItem>
public class DocumentTypeViewModel
{
ModuleRepository _modulerepository = new ModuleRepository();
public tbl_DocumentTypes Document { get; private set; }
public IEnumerable<SelectListItem> Modules { get; private set; }
public DocumentTypeViewModel(tbl_DocumentTypes document)
{
Document = document;
//var _modules = _modulerepository.FindAllModules().Select(d => new {Module_Id= SqlFunctions.StringConvert((double?)d.Module_Id), Text = d.ModuleName });
Modules = _modulerepository.FindAllModules()
.Select(d => new SelectListItem
{
Value= SqlFunctions.StringConvert((double?)d.Module_Id),
Text = d.ModuleName
});
}
}
And in your view:
<div class="editor-label">Module</div>
<div class="editor-field">
#Html.DropDownList("Document.Module_Id", Model.Modules)
#Html.ValidationMessageFor(model => model.Document.Module_Id)
</div>
I have the following form:
#model Teesa.Models.SearchModel
#using (Html.BeginForm("Index", "Search", FormMethod.Get, new { id = "SearchForm" }))
{
<div class="top-menu-search-buttons-div">
#if (!MvcHtmlString.IsNullOrEmpty(Html.ValidationMessageFor(m => m.SearchText)))
{
<style type="text/css">
.top-menu-search-text
{
border: solid 1px red;
}
</style>
}
#Html.TextBoxFor(q => q.SearchText, new { #class = "top-menu-search-text", id = "SearchText", name = "SearchText" })
#Html.HiddenFor(q=>q.Page)
<input type="submit" value="search" class="top-menu-search-submit-button" />
</div>
<div id="top-menu-search-info" class="top-menu-search-info-div">
Please Select one :
<hr style="background-color: #ccc; height: 1px;" />
<div class="top-menu-search-info-checkbox-div">
#Html.CheckBoxFor(q => q.SearchInBooks, new { id = "SearchInBooks", name = "SearchInBooks" })
<label for="SearchInBooks">Books</label>
</div>
<div class="top-menu-search-info-checkbox-div">
#Html.CheckBoxFor(q => q.SearchInAuthors, new { id = "SearchInAuthors" })
<label for="SearchInAuthors">Authors</label>
</div>
<div class="top-menu-search-info-checkbox-div">
#Html.CheckBoxFor(q => q.SearchInTags, new { id = "SearchInTags" })
<label for="SearchInTags">Tags</label>
</div>
}
and the following Controller and Models :
namespace Teesa.Models
{
public class SearchModel
{
[Required(ErrorMessage = "*")]
public string SearchText { get; set; }
public bool SearchInTags { get; set; }
public bool SearchInAuthors { get; set; }
public bool SearchInBooks { get; set; }
public int Page { get; set; }
public List<SearchBookModel> Result { get; set; }
public List<SimilarBookModel> LatestBooks { get; set; }
}
public class SearchBookModel
{
public int Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public string Summary { get; set; }
public List<Tags> Tags { get; set; }
public string StatusName { get; set; }
public string SubjectName { get; set; }
public string ThumbnailImagePath { get; set; }
public string BookRate { get; set; }
public string RegistrationDate { get; set; }
public int NumberOfVisit { get; set; }
}
}
[HttpGet]
public ActionResult Index(SearchModel model)
{
FillSearchModel(model);
if (ModelState.IsValid)
{
string page = model.Page;
DatabaseInteract databaseInteract = new DatabaseInteract();
model.Result = new List<SearchBookModel>();
List<Book> allBooks = databaseInteract.GetAllBooks();
List<Book> result = new List<Book>();
#region
if (model.SearchInTags)
{
var temp = (from item in allBooks
from tagItem in item.Tags
where tagItem.Name.Contains(model.SearchText)
select item).ToList();
result.AddRange(temp);
}
if (model.SearchInBooks)
{
var temp = (from item in allBooks
where item.عنوان.Contains(model.SearchText)
select item).ToList();
result.AddRange(temp);
}
if (model.SearchInAuthors)
{
var temp = (from item in allBooks
where item.Author.Contains(model.SearchText)
select item).ToList();
result.AddRange(temp);
}
#endregion
#region Paging
string itemsPerPage = databaseInteract.GetItemsPerPage();
int ItemInPage = int.Parse(itemsPerPage);
var pagingParams = Helpers.SetPagerParameters(page, ItemInPage, result);
ViewBag.AllPagesCount = pagingParams.AllPagesCount;
ViewBag.CurrentPageNumber = pagingParams.CurrentPageNumber;
ViewBag.CountOfAllItems = pagingParams.CountOfAllItems.ToMoneyFormat().ToPersianNumber();
result = pagingParams.ListData as List<Book> ?? result;
#endregion
foreach (var item in result)
{
var bookRate = (item.BookRate == null || item.BookRate.Count == 0)
? 0.0
: item.BookRate.Average(q => q.Rate);
model.Result.Add(new SearchBookModel
{
Author = item.Author,
Id = item.Id,
.
.
.
});
}
}
else
{
model.Result = new List<SearchBookModel>();
}
return View(model);
}
When I submit the form I see the following query strings(Notice the duplicate names) :
http://localhost:2817/Search?SearchText=book&Page=2&SearchInBooks=true&SearchInBooks=false&SearchInAuthors=true&SearchInAuthors=false&SearchInTags=true&SearchInTags=false
But it has to be something like this :
http://localhost:2817/Search?SearchText=book&Page=2&SearchInBooks=true&SearchInAuthors=true&SearchInTags=true
How can I fix it ?
Thanks
Html.Checkbox (and the related For... methods) generate a hidden input for false, and the checkbox for true. This is to ensure that model binding works consistently when binding.
If you must get rid of "false" items resulting from the hidden inputs, you'll need to construct the checkbox inputs yourself (using HTML and not the helper).
<input type="checkbox" id="SearchInBooks" name="SearchInBooks">
Why dont your create a Post Method with a matching name to the Get method. This will ensure that the code is much easier to debug. As you will not have a huge function to go through trying to find problems like this.
I cannot find a where your getting the duplicate url query strings from though.
This will also allow you to bind your results back to the model.
If you want the model binding to happen successfully then you have to go with this way because that is the nature of the Html.CheckBox/Html.CheckBoxFor methods they will render a hidden field as well.
I would suggest rather go with POST to make your life easy. If you still want to use GET then you have to use checkbox elements directly but you have to take care of the model binding issues. Not all the browsers returns "true" when the checkbox is checked for ex. firefox passes "on" so the default model binder throws an error.
Other alternate options is you can go for custom model binder or you can submit the form using jquery by listening to the submit event.