I am facing a bit of problem editing and deleting rows from SQL in ASP.NET MVC. The main problem I am facing is the fetch the QueryString value from url in my controller.
I can't attach Request.QueryString["Username"] for some reason. It is giving me Can not apply indexing with [] to an expression of type QueryString error.
Is there something I am doing it wrong or is there any way I can pass the QueryParameter through my controller to my Data access layer, where it will execute the desired query.
I am having the same problem with both Edit and Delete
This is my code looks like so far:
ShowUsers.cshtml (Edit and Delete actions are hooked up here)
#model IEnumerable<SecureMedi.Models.Users>
<section id="users">
<table id="users-table" class="table table-bordered table-responsive">
<thead>
<tr>
<th class="sort">Username</th>
<th class="sort">Role</th>
<th class="sort"><i class="md-icon dp18">mode_edit</i></th>
<th class="sort"><i class="md-icon dp18">delete</i></th>
</tr>
</thead>
<tbody class="list">
#foreach (var item in Model) {
<tr>
<td class="username">#item.Username</td>
<td class="role">#item.Role</td>
<td class="actions">#Html.ActionLink("Edit", "EditUser", "Home", new { Username = #item.Username }, null)</td>
<td class="actions">#Html.ActionLink("Delete", "DeleteUser", "Home", new { Username = #item.Username }, null)</td>
</tr>
}
</tbody>
</table>
</section>
EditUser.cshtml (For Editing) - Note: Here I would also like to display the Username value by default from the QueryString (Username=somename) in the form when the page loads. When going to EditUser action from ShowUsers page the url looks something like /Home/EditUser?Username=somename.
#model SecureMedi.Models.Users
<section id="edit-user">
<h4 class="sub-title space-top space-bottom">Edit user</h4>
<form id="edit-user-form" asp-controller="Home" asp-action="EditUser" method="post">
<div class="form-group">
<label asp-for="Username" class="form-control-label">Username</label>
<input asp-for="Username" type="text" class="form-control" id="username" name="Username" required disabled value="" />
</div><!-- / form-group -->
<div class="form-group">
<label asp-for="Role">Role</label>
<select asp-for="Role" class="form-control selector" id="role" name="Role" required>
<option value="" selected disabled>Select role</option>
<option value="SecureMediUsers">SecureMediUsers</option>
<option value="SecureMediModerators">SecureMediModerators</option>
<option value="SecureMediAdministrators">SecureMediAdministrators</option>
</select>
</div><!-- / form-group -->
<button type="submit" class="btn btn-primary">Save</button>
</form><!-- / form -->
</section>
HomeController.cs
[HttpGet]
public IActionResult EditUser() {
var model = new Users();
return View(model);
}
[HttpPost]
public IActionResult EditUser(Users u) {
if (!ModelState.IsValid) {
return View(u);
}
UsersDAL ud = new UsersDAL();
ud.Edit(u);
return RedirectToAction("ShowUsers");
}
[HttpPost]
public IActionResult DeleteUser(Users u) {
if (!ModelState.IsValid) {
return View(u);
}
UsersDAL ud = new UsersDAL();
ud.Delete(u);
return RedirectToAction("ShowUsers");
}
UsersDAL.cs (Data access layer)
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using SecureMedi.Models;
namespace SecureMedi.DAL {
public class UsersDAL {
public void Edit(Users u) {
string connectionstring = "MY_CONNECTION_STRING";
string sql = String.Format("ALTER ROLE {0} DROP MEMBER {1}", u.Role, u.Username);
string sql2 = String.Format("ALTER ROLE {0} ADD MEMBER {1}", u.Role, u.Username);
SqlConnection conn = new SqlConnection(connectionstring);
SqlCommand cmd = new SqlCommand(sql, conn);
SqlCommand cmd2 = new SqlCommand(sql2, conn);
try {
conn.Open();
using(conn) {
cmd.Transaction = conn.BeginTransaction();
cmd.ExecuteNonQuery();
cmd2.Transaction = cmd.Transaction;
cmd2.ExecuteNonQuery();
cmd2.Transaction.Commit();
}
} finally {
if (conn != null) {
conn.Close();
}
}
}
public void Delete(Users u) {
string connectionstring = "MY_CONNECTION_STRING";
string sql = String.Format("DROP USER {0}", u.Username);
SqlConnection conn = new SqlConnection(connectionstring);
SqlCommand cmd = new SqlCommand(sql, conn);
try {
conn.Open();
using(conn) {
cmd.ExecuteNonQuery();
}
} finally {
if (conn != null) {
conn.Close();
}
}
}
}
}
Users.cs (Model)
using System.ComponentModel.DataAnnotations;
namespace SecureMedi.Models {
public class Users {
[Required]
[StringLength(100)]
public string Username {
get;
set;
}
[Required]
[StringLength(100)]
public string Role {
get;
set;
}
}
}
In summary, the problems I am trying to solve are:
1) Passing the Username query param from EditUser view and Role value from the form to my EditUser controller function.
2) I have hooked up the delete action like
<td class="actions">#Html.ActionLink("Delete", "DeleteUser", "Home", new { Username = #item.Username }, null)</td>
But I'm confused on to how to avoid the [HttpGet] for DeleteUser action. When I click on the anchor tag it is taking me to /Home/DeleteUser?Username=somename, but instead I would just like to execute the DeleteUser action without the view change.
Also, how do I pass Username query param to the controller action.
1) Change [HttpGet] EditUser to take UserName parameter:
and get user by UserName to send this data to model:
[HttpGet]
public IActionResult EditUser(string UserName) {
var model = new Users(UserName);//probably, Or something like GetUser(UserName)
return View(model);
}
2) You can't call HTTPPost method by using actionLink. It will always use HttpGet. So there is two approaches that you can use - 1. Delete user in HttpGet and than redirect to previous page
2. Use JavaScript to call HttpPost, instead of send HttpGet by action link clicking.
You Just Want to Delete the recor form database on just click on the delete link without confirmation user should be navigated to the same page .?
these changes will do this trick for you ! tried
Update your Home Controller Like :
i just remove the [httppost] from delete actionResult and change the parameter name and also write the controller name also in your return redirecttoaction
IMP NOTE : Update The Paramete Users To Username where ever u use it like in DAL Also Suggestion is to use the same one everywhere either it would be null
HomeController.cs
[HttpGet]
public IActionResult EditUser() {
var model = new Users();
return View(model);
}
[HttpPost]
public IActionResult EditUser(Users u) {
if (!ModelState.IsValid) {
return View(u);
}
UsersDAL ud = new UsersDAL();
ud.Edit(u);
return RedirectToAction("ShowUsers", "ControllerName");
}
public IActionResult DeleteUser(Username u) {
if (!ModelState.IsValid) {
return View(u);
}
UsersDAL ud = new UsersDAL();
ud.Delete(u);
return RedirectToAction("ShowUsers", "ControllerName");
}
Related
I'm new with asp.net MVC and studying with some example code.
I'm referrence the sample from https://github.com/LaunchCodeEducation/cheese-mvc.
And I want to add new action and view for the example. Such as add a delete link/button to delete a cheese from cheese/index page directly:
But it seems there have something wrong with the SingleRemove action and view I wrote.
The action I use as below:
[HttpGet]
public IActionResult SingleRemove()
{
ViewBag.cheeses = context.Cheeses.ToList();
return View();
}
[HttpPost]
public IActionResult SingleRemove(int cheeseId)
{
Cheese theCheese = context.Cheeses.Single(c => c.ID == cheeseId);
//context.Cheeses.Remove(theCheese);
//context.SaveChanges();
return View(theCheese);
}
And the view I use as :
#model CheeseMVC.Models.Cheese
<h1>Going to be removed cheese information as below</h1>
<form >
<ul>
<li>Cheese ID: #Model.ID</li>
<li>Cheese Name: #Model.Name</li>
<li>Cheese Type: #Model.Type</li>
<li>Cheese Description: #Model.Description</li>
</ul>
<input type="submit" value="Remove Selected Cheese" />
</form>
Could you please guide how to set the action and model correctly?
And how to let a pop-up window to double confirm the deletion on a cheese?
If you create a Controller and select "Controller with views, using Entity Framework" it will create all of that for you based on your model. You could then go back and make it pretty with ccs to use buttons instead of links ect.. I am not sure what your view is doing in the above code. Your view should be
<table class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Description</th>
<th></th>
</tr>
</thead>
foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.Name)</td>
<td>#Html.DisplayFor(modelItem => item.Type)</td>
<td>#Html.DisplayFor(modelItem => item.Description)</td>
<td>
#using (Html.BeginForm("Delete", "controller name goes here", FormMethod.Post))
{
#Html.AntiForgeryToken()
<input type="hidden" id="id" value="#item.ID" />
<input onclick="return confirm('Are you sure you want to delete the Cheese?');" type="submit" value="Delete" class="btn btn-primary " />
}
</td>
</tr>
}
</table>
Then in your Controller you would have something like this:
public ActionResult Delete(int? ID)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Cheese cheese = db.Cheese.Find(id);
if (cheese == null)
{
return HttpNotFound();
}
return View(Index);
}
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult Delete(int ID)
{
var cheese = db.cheese.Find(id);
if (cheese != null)
{
Cheese cheese = db.Cheese.Find(id);
db.Cheese.Remove(cheese);
db.SaveChanges();
return RedirectToAction("Index");
}
return RedirectToAction("Index", "Cheese");
}
Make sure your are using:
using System.Data.Entity;
using System.Linq;
using System.Net;
And also not sure what your context is but this is where the db.Cheese comes from:
private ApplicationDbContext db = new ApplicationDbContext();
I want to create a button that changes a string data in the database. Currently in the database, there is a table for AspNetUsers which contains a string column called Activated (default value is null). What I would like to happen is when a button is clicked, that null value becomes the value 'Yes' on buttonclick. How do I go about doing this with MVC? Thanks
This is the button Im calling in the view
#model IEnumerable<ProjectMVC2.Models.ApplicationUser>
#foreach (var item in Model)
{
#if (item.Activated == null)
{
using (Html.BeginForm("Update", "User", new { id = item.Id })){
#Html.AntiForgeryToken()
<td class="button btn-default" align="center">
<input type="submit" value="Activate" class="btn btn-default" />
</td>
}
}
else if (item.Activated == "Yes")
{
<td class="c" align="center">
Activated already
</td>
}
This is the controller. There is a method called Update which I am calling for the button in the view
public class UserController : BaseController
{
ApplicationDbContext context;
private SqlConnection update;
private SqlCommand set;
public UserController()
{
context = new ApplicationDbContext();
}
// GET: User
public ActionResult Index()
{
var User = context.Users.ToList();
return View(User);
}
public ActionResult Update(int id)
{
update = new SqlConnection(#"Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=C:\Users\WinUser\Desktop\ProjectMVC2\ProjectMVC2\App_Data\aspnet-ProjectMVC2-20180223023456.mdf;Initial Catalog=aspnet-ProjectMVC2-20180223023456;Integrated Security=True");
update.Open();
set = new SqlCommand("UPDATE AspNetUsers SET Activated = 'Yes' ");
return RedirectToAction("Index");
}
}
This Update method does not work. How can i fix this please? I appreciate any help. Thank you very much
I would like to have a button where on click it changes a string value from null to any other text (for example 'yes'). I have a button in the view that calls an update method in the controller but I don't know what to put inside that update method.
In the view, this is the button ('item' refers to model, 'Activated' refers to a string column in that model which has a default value of null)
#model IEnumerable<ProjectMVC2.Models.ApplicationUser>
#foreach (var item in Model)
{
#if (item.Activated == null)
{
using (Html.BeginForm("Update", "User", new { id = item.Id })){
#Html.AntiForgeryToken()
<td class="button btn-default" align="center">
<input type="submit" value="Activate" class="btn btn-default" />
</td>
}
}
else if (item.Activated == "Yes")
{
<td class="c" align="center">
Activated already
</td>
}
I have the method in my controller
public class UserController : BaseController
{
ApplicationDbContext context;
public UserController()
{
context = new ApplicationDbContext();
}
// GET: User
public ActionResult Index()
{
var User = context.Users.ToList();
return View(User);
}
public ActionResult Update()
{
return RedirectToAction("Index")
}
}
In the method what should I put that will allow for the change to happen? Please if anyone can help, I will really appreciate it.
You'll have to updated your model itself:
public ActionResult Update()
{
var users = context.Users.ToList();
foreach(var user in users)
{
user.Activated = "Yes";
}
context.SaveChanges();
return RedirectToAction("Index")
}
However, this changes are persisted so if you come back to the page again you'll still see user.Activated = "Yes". If you need something temporary, I would suggest to use following code.
public ActionResult Update()
{
var users = context.Users.ToList();
foreach(var user in users)
{
user.Activated = "Yes";
}
return View("Index", users);
}
Use a for loop to take advantage of model binding to a collection.
This is accomplished by using an indexing expression e.g. Model[i].
Add a HiddenFor to tell the controller which users need to be activated.
#for (var i = 0; i < Model.Length; i++)
{
var item = Model[i];
#if (item.Activated == null)
{
using (Html.BeginForm("Update", "User", new { id = item.Id }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(_ => Model[i].Id)
<td class="button btn-default" align="center">
<input type="submit" value="Activate" class="btn btn-default" />
</td>
}
}
else if (item.Activated == "Yes")
{
<td class="c" align="center">
Activated already
</td>
}
The update method now accepts a collection of users to activate.
public ActionResult Update(IEnumerable<ApplicationUser> usersToActivate)
{
// Are there any user to active?
if (usersToActivate == null)
{
return View();
}
var userIds = usersToActivate.Select(u => u.Id).ToList();
var usersToUpdate = context.Users.Where(user => userIds.Contains(user.Id));
foreach (var userToUpdate in usersToUpdate)
{
userToUpdate.activated = "Yes";
}
context.SaveChanges();
return RedirectToAction("Index")
}
I am having difficulty passing an IEnumerable as a model. The data is populating a form on one page - and doing so correctly. Upon submission the model returns as null.
I've seen various posts on this and they mostly reference naming-conventions so I have attempted different methods of naming the parameters to try to avoid any confusion in the model binding.
I have also tried various models and helpers to try and pass the data and all have the same result.
Current implementation:
Models:
public class UserProfileListModel
{
public IEnumerable<UserProfileViewModel> UserProfileViewModels { get; set; }
}
public class UserProfileViewModel
{
public UserProfile UserProfile { get; set; }
public Role UserRole { get; set; }
public Team UserTeam { get; set; }
public Scope UserScope { get; set; }
}
View:
#model Project.WebUI.Models.UserPRofileListModel
SNIP
<fieldset>
<legend>Administrate Users:</legend>
<table class="adminTbl">
<thead>
<tr>
<th>UserName:</th>
<th>Role:</th>
<th>Team:</th>
<th>Scope:</th>
<th>Update:</th>
<th>Delete:</th>
</tr>
</thead>
<tbody>
#{foreach (var user in Model.UserProfileViewModels)
{
<tr>
<td>
<p>#user.UserProfile.UserName
#{if (!user.UserProfile.Membership.IsConfirmed)
{
using (Html.BeginForm("Confirm", "Account", FormMethod.Post, null)){
#Html.AntiForgeryToken()
#Html.Hidden("Token", user.UserProfile.Membership.ConfirmationToken)
#Html.Hidden("Name", user.UserProfile.UserName)
}
<input type="submit" value="Confirm" />}
}
</p>
</td>
#{using (Html.BeginForm("SaveUserChanges", "Account", FormMethod.Post, null))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(u => user.UserProfile)
if (user.UserProfile.UserName != User.Identity.Name && user.UserProfile.Membership.IsConfirmed)
{
<td>
#Html.DropDownListFor(u => user.UserRole, Project.WebUI.Controllers.AccountController.RoleList, new { #class = "formdrop" })
</td>
<td>
#Html.DropDownListFor(u => user.UserTeam, Project.WebUI.Controllers.AccountController.TeamList, new { #class = "formdrop" })
</td>
<td>
#Html.DropDownListFor(u => user.UserScope, Project.WebUI.Controllers.AccountController.ScopeList, new { #class = "formdrop" })
</td>
<td>
<input type="submit" value="Save Changes" onclick="return confirm('Are you sure you wish to update this user? ')" />
</td>
}
else
{
/*If user is self or not yet confirmed these are here to buffer the delete button into the last cell*/
<td></td>
<td></td>
<td></td>
<td></td>
}
}
}
<td>
#Html.ActionLink("Delete", "Delete", new { user.UserProfile.UserId }, new
{
onclick = "return confirm('Warning: Action cannot be undone. Are you sure you wish to permanently delete this entry?')"
})
</td>
</tr>
}
}
</tbody>
</table>
</fieldset>
Controller:
Populate View:
public ActionResult AdministrateUsers()
{
populateLists();
var query = repository.UserProfiles.OrderBy(e => e.UserName);
List<UserProfileViewModel> list = new List<UserProfileViewModel>();
foreach(UserProfile up in query)
{
UserProfileViewModel vm = new UserProfileViewModel() { UserProfile = up };
list.Add(vm);
}
UserProfileListModel models = new UserProfileListModel()
{
UserProfileViewModels = list.OrderBy(up => up.UserProfile.UserName)
};
return View(models);
}
Accept Post:
public ActionResult SaveUserChanges(UserProfileListModel model)
{
foreach (UserProfileViewModel upvm in model.UserProfileViewModels)
{
UserProfile up = new UserProfile()
{
UserId = upvm.UserProfile.UserId,
UserEmail = upvm.UserProfile.UserName,
UserName = upvm.UserProfile.UserName
};
if (ModelState.IsValid)
{
repository.SaveUserProfile(up);
}
else
{
return View(model);
}
}
return RedirectToAction("Index", "Admin");
}
The code does still need a lot of work but I can't get past getting the model back to the controller on post. I have also tried returning the UserProfileViewModel instead of the entire list.
Can anyone tell what I am doing wrong?
Thanks!
You have a lot of invalid html including form elements as child elements of tr elements and duplicate id attributes. If you want to post back UserProfileListModel then you need a single form element and use an EditorTemplate or a for loop (not foreach) to render the controls so they are correctly named with indexers.
You are also trying to bind your dropdown lists to complex objects (for example UserProfile, Role etc.). <select> elements (and all form controls) only post back key/value pairs so you need to bind to a value type (for example UserProfile.UserId).
Your SaveUserChanges() post method is also trying access properties of UserProfile but you don't even have controls for properties of UserProfile in the form that post back to this method (for example UserId = upvm.UserProfile.UserId, UserEmail = upvm.UserProfile.UserName, ...) so they will always be null.
You probalby need to bind properties in POST method like here:
public ActionResult Create([Bind(Include = "Id,Subject,Text,IsImportant")] Announcment announcment) {... }
So it will be:
public ActionResult SaveUserChanges([Bind(Include = "UserProfile,Role,UserTeam,UserScope")]UserProfileListModel model)
Have you specified your action method is for HTTP Post? And change your action method to accept UserProfileViewModels instead.
[HttpPost]
public ActionResult SaveUserChanges(UserProfileViewModels model)
{
You are also only posting back one model: UserProfileViewModels.
You have your form in your foreach loop, so each UserProfileViewModels has its own form. If you want to change it to post back your UserProfileListModel, move
#{using (Html.BeginForm("SaveUserChanges", "Account", FormMethod.Post, null))
outside of your foreach.
I have a PaartialView declared like this:
#model IEnumerable<mvc1.Models.ProjectDetailModel>
#using (Html.BeginForm())
<form method="get" action="EditProject" enctype="multipart/form-data">
<br />
<fieldset>
<legend>Project Detail</legend>
#foreach (var item in Model)
{
<tr>
<th class="thdetail">
Project Code
</th>
<td class="tddetail">
#Html.DisplayFor(modelItem => item.projectCode)
</td>
<tr>
<th class="thdetail">
Project Name
</th>
<td class="tddetail">
#Html.DisplayFor(modelItem => item.projectName)
</td>
</tr>
<tr>
<th class="thdetail">
Project Type
</th>
<td class="tddetail">
#Html.DisplayFor(modelItem => item.projectType)
</td>
</tr>
<tr>
<th class="thdetail">
Detailed Description
</th>
<td class="tddetail">
<div style="height: 100px; width:700px; overflow: scroll">
#Html.DisplayFor(modelItem => item.projectDescription)
</div>
</td>
</tr>
</table>
</fieldset>
<input type="submit" value="Edit" />
</form>
}
On the submit button, i am calling a controller, but when it goes to the controller the model is not being passed back to the controller. How can i get the model back to the controller, or even just 1 field, ie. Model.projectCode which is the primary key
In the controller i have the fll which takes in the model and gets the primary key and calls a stored procedure to return results to another VIEW()
[HttpGet]
public ActionResult EditProject(ProjectDetailModel model)
{
DBController dbcontroller = new DBController();
string l_user_name = SessionBag.Current.UserName;
Int64 l_project_code = model.projectCode;
if (dbcontroller.DBConnection())
{
MySqlCommand command = new MySqlCommand("edit_projects", dbcontroller.conn);
command.CommandType = System.Data.CommandType.StoredProcedure;
// Input parameters for the insert_projects STORED PROC
command.Parameters.Add(new MySqlParameter("userName", SessionBag.Current.UserName));
command.Parameters["#userName"].Direction = System.Data.ParameterDirection.Input;
// Output parameters for the view_sr_projects_detail STORED PROC
command.Parameters.Add(new MySqlParameter("projectName", MySqlDbType.LongText));
command.Parameters["#projectName"].Direction = System.Data.ParameterDirection.Output;
command.Parameters.Add(new MySqlParameter("projectType", MySqlDbType.LongText));
command.Parameters["#projectType"].Direction = System.Data.ParameterDirection.Output;
command.Parameters.Add(new MySqlParameter("projectDescription", MySqlDbType.LongText));
command.Parameters["#projectDescription"].Direction = System.Data.ParameterDirection.Output;
try
{
MySqlDataReader rdr = command.ExecuteReader();
var model1 = new ProjectDetailModel();
while (rdr.Read())
{
model1.projectCode = (Int64)(rdr["projectCode"]);
model1.projectName = rdr["projectName"].ToString();
model1.projectType = rdr["projectType"].ToString();
model1.projectDescription = rdr["projectDescription"].ToString();
}
dbcontroller.conn.Close();
return View(model1);
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
dbcontroller.conn.Close();
ViewBag.Message = "Could not view your detail project. Error " + ex.Number + " has ocurred. Please try again or contact the system administrator.";
return View("Error");
}
}
else
{
ViewBag.Message = "Could not connect to the database. Please try again or contact the system administrator";
return View("Error");
}
}
My model looks like this:
public class ProjectDetailModel
{
[Display(Name = "Project Code")]
public Int64 projectCode { get; set; }
[Display(Name = "User Name")]
public string srUserName { get; set; }
[Display(Name = "Project Name")]
public string projectName { get; set; }
[Display(Name = "Project Type")]
public string projectType { get; set; }
[Display(Name = "Project Requirement")]
public string projectDescription { get; set; }
}
public class ProjectDetailModelList : List<ProjectDetailModel>
{
}
thanks
Naren
Here this is what you can do. Below is just partial code, modify it to fit in with your example:
Code in your view:
<button id="btnEdit" type="button">Edit</button>
I then use jQuery to add a click listener to the button (make sure that jQuery is added to the view):
<script>
$(document).ready(function () {
$('#btnEdit').click(function () {
window.location = '#Url.RouteUrl(new { action = "EditProject", projectCode = Model.projectCode })';
});
});
</script>
Your action method:
public ActionResult EditProject(int projectCode)
{
// Retrieve this specific project using this code
// Do what needs to be done to populate the required input fields on view
}
This is the best way that I have found to do it.
When MVC calls your controller.EditProject(ProjectDetailModel) action the binding system tries to create a ProjectDetailModel object from the data posted to the page (or in the query string or route data, etc.). In order for it to create and populate a ProjectDetailModel for you, you must have the following:
A parameterless constructor on ProjectDetailModel
A publically-settable property with a matching value in the form data
So if ProjectDetailModel looks like this:
public class ProjectDetailModel
{
public ProjectDetailModel()
{
}
public int ProjectId
{
get;
set;
}
}
...you can have it populated by MVC by posting this form:
<form method="get" action="EditProject" enctype="multipart/form-data">
<input type="hidden" id="ProjectId" name="ProjectId" value="123" />
</form>
Edit
Looking at the extra code you've added to the question, you have a few things to sort out:
#using (this.Html.BeginForm()) will render an open form tag - as you've manually written one you don't need that line.
Using this.Html.DisplayFor() will just write the property value to the screen; if you want it to be populated into a parameter in your action, you need to provide the values to the binding system. You can do this by using EditorFor() instead of DisplayFor(), which will cause them to be included in the request as it is sent to the action.