Blazor Server - Insert CustomerID when inserting a Project to another table - c#

My project has a few tiers here. Customer -> Project
The Project Table has a value for the CustomerID.
I'm getting a list of CustomerNames using my CustomersModel.
Simple example of what I'm trying to do here. Choose a customer from a list and then type in a new Project Name and submit that to a table. Binding the CustomerID causes the "Chose a Customer" option to not show up in the select drop down. If I put CustomerName is the bound value it will show as the placeholder for the drop down.
But I need to pass the CustomerID to the Projects Table with the new Project Name.
I'm not sure what I'm missing here.
--
Component Code
<EditForm Model="#newProject" OnValidSubmit="#InsertLocation">
<DataAnnotationsValidator />
<div class="form-group">
<div class="row">
<div class="col-md-5">
<label class="form-label">Customer Name</label>
<InputSelect class="form-control" id="CustomerName" #bind-Value="newProject.CustomerID">
#if (customer is null)
{
}
else
{
<option selected disabled value="-1"> Choose a Customer</option>
#foreach (var customer in customers)
{
<option>#customer.CustomerName</option>
}
}
</InputSelect>
#*<ValidationMessage For="(() => newProject.CustomerID)" />*#
</div>
<div class="col-md-5">
<label class="form-label">Location Name</label>
<InputText class="form-control" id="ProjectName" #bind-Value="newProject.ProjectName" placeholder="Location Name" />
<ValidationMessage For="(() => newProject.ProjectName)" />
</div>
</div>
#code from the component
private ProjectsViewModel newProject = new ProjectsViewModel();
private async Task InsertLocation()
{
//assign the new project data to the project model in the back end
ProjectsModel project = new ProjectsModel
{
//TODO: make these match what is in the model and update insert query
ProjectName = newProject.ProjectName,
CustomerID = newProject.CustomerID
};
await projectsData.InsertLocation(project); //send data to db
newProject = new ProjectsViewModel();
projects = await projectsData.ReadProjects();
OpenAddLocationModal = false;
}
And finally sending to the stored procedure from the projectData file.
public async Task InsertLocation(IProjectsModel project)
{
var p = new
{
project.CustomerID,
project.ProjectName
};
await _db.SaveData("dbo.spProject_Create", p, "DefaultConnection");
}
SQL Procedure
#ProjectName nvarchar(255),
#CustomerID int
as
begin
insert into dbo.Projects(CustomerID, ProjectName)
values (#CustomerID, #ProjectName);
end
Thanks for any help.

Related

Filling input boxes in Bunit blazor Unit test

I have a blazor page with some input boxes and a button to submit the data. There is then code to validate and upload the data to a database after passing validation.
#page "/register"
<h2>
Create account
</h2>
<EditForm Model="_model" OnSubmit="#Submit">
<div>
<div class="form-group">
<label>Display name</label>
<InputText #bind-Value="_handle" class="form-control" />
</div>
<div class="form-group">
<label>Email</label>
<InputText #bind-Value="_email" type="email" class="form-control" />
</div>
<div class="form-group">
<label>Password</label>
<InputText #bind-Value="_password" type="password" class="form-control" />
</div>
<div class="form-group">
<label>Re-enter password</label>
<InputText #bind-Value="_repeatPassword" type="password" class="form-control" />
</div>
<div class="d-grid">
<button type="button" class="btn btn-primary" #onclick="Submit">Create your account</button>
</div>
</div>
</EditForm>
<div>
Sign in
</div>
#code {
private object _model = new object();
private string _firstname;
private string _lastname;
private string _handle;
private string _email;
private string _password;
private string _repeatPassword;
// -- validate inputs -- //
// -- Add to Database -- //
var user = new User
{
Id = Guid.NewGuid(),
Username = _email.ToLowerInvariant(),
Handle = _handle,
Password = password,
PasswordSalt = passwordSalt,
Firstname = _firstname,
Lastname = _lastname,
CreatedOn = DateTime.UtcNow,
};
context.Users.Add(user);
await context.SaveChangesAsync(default);
}
Recently I decided to set up unit testing for my razor pages and I am currently stuck on how to verify that a user is actually being created with the given data. I will say I know that my code is working because I can see the correct data being added to the database but I don't want to test potential changes in the future by looking at the database. I would like to be able to test it by the unit test. Here is what I have so far, I think I am close but not quite sure how to fill the input boxes and then hit submit to see the user is created. Is this possible? My unit test code is below.
namespace ZachUnitTests.ZachUnitTests.Pages;
public class RegisterTests
{
[Test]
public void VerifyUserData()
{
// Arrange
using var ctx = new Bunit.TestContext();
// Act
var cut = ctx.RenderComponent<Register>();
var inputs = cut.FindAll(".form-group");
var input1 = inputs.Where(x => x.ParentElement.TextContent.Contains("Display name")).FirstOrDefault();
input1.Input("Zachrules123"); //doesn't work because there is no #oninput .. How do I fill this box?
var input2 = inputs.Where(x => x.ParentElement.TextContent.Contains("Email")).FirstOrDefault();
input2.Input("Zachrules123#gmail.com"); //doesn't work because there is no #oninput .. How do I fill this box?
var input3 = inputs.Where(x => x.ParentElement.TextContent.Contains("Password")).FirstOrDefault();
input3.Input("password"); //doesn't work because there is no #oninput .. How do I fill this box?
var input4 = inputs.Where(x => x.ParentElement.TextContent.Contains("Re-enter password")).FirstOrDefault();
input4.Input("password"); //doesn't work because there is no #oninput .. How do I fill this box?
cut.Find("button").Click();
//Assert
//User is created
}
}
The error message from bUnit tells you what other event handler are actually bound to the object. You can also check cut.Markup and see what event handler are bound. But it is likely onchange, so use the Change() method instead of Input().

How to get rid of the foriegn key exception in mvc

I have a module in my project where in a functionality I have a textbox where I am entering a missing note and saving it with button, but the table where I am saving the data is having a foreign key and I am getting the following exception
My code is as follows
public ActionResult SetBreakageNote(int id, string MissNote, int charge)
{
var Rdetail = new ReservationDetail();
if (ModelState.IsValid)
{
Rdetail.ReservationID = id;
Rdetail.Description = MissNote;
Rdetail.ChargeType = charge;
db.Insert(Rdetail);
}
return RedirectToAction("Index");
}
My View
#model IEnumerable<RoomTypeView>
<div class="row">
#foreach (var item in Model)
{
<div class="col-3">
<div class="row">
<div class="col-8">
<div class="inventory my-1">
<textarea class="form-control breakage" placeholder="Enter Breakage Note" rows="1"></textarea>
</div>
</div>
<div class="col-4">
<button type="button" class="btn btn-default breakage" data-brid="#item.ReservationID"><i class="fa fa-file-invoice" style="color:red;"></i></button>
</div>
</div>
</div>
}
</div>
$('.breakage').click(function () {
$.post("#Url.Action("SetBreakageNote", "HouseKeeping")", { id: $(this).data('brid'), MissNote: $('.breakage').val(), charge: #((int)ChargeTypeEnum.Breakage) });
});
Here is the exception I am getting
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_ReservationDetails_Reservation". The conflict occurred in database "CavalaV3DB", table "dbo.Reservation", column 'ReservationID
ReservationID is a foreign key for Reservation table.
Please help me with this
You are trying to insert some value into your Rdetail in ReservationID column. But that value is not there in Reservation table.
This is violating Foreign key constraint created in the Rdetail table.
You can avoid this by checking this before inserting data into the table
if (ModelState.IsValid)
{
if(db.Reservation.where(a=>a.ReservationId==id).Amy()) //Condition to check if data is there or not
{
Rdetail.ReservationID = id;
Rdetail.Description = MissNote;
Rdetail.ChargeType = charge;
db.Insert(Rdetail);
}
}
Before data can be inserted, the value in the foreign key field must exist in the other table first.You must build the table containing the Primary Key first after that you can populate them in a drop down from where you need to select first to save data.
the best way to deal with foreign key in other table's View Bind them in a Drop Down List and set attribute required

How to get a SelectedValue #Html.DropDownList and INSERT into Database in Razor C#

I have a dropdownlist, which I have filled with items from a database. The dropdownlist displays the item name however the value when selected is the ID of the item and not the name.
I want to insert this a new record on a different table but I am getting the following error and I have attempted to research the problem:
Compiler Error Message: CS0103: The name 'customerID' does not exist in the current context
#{
Layout = "~/_Layout.cshtml";
Page.Title = "Add Server";
var db = Database.Open("BackupMonitoringAppV2") ;
var listcustomers = "SELECT CustomerName, CustomerID from Customers";
List<SelectListItem> customerdropdowndata = new List<SelectListItem>();
bool isSelected = false;
foreach(var item in db.Query(listcustomers)){
customerdropdowndata.Add(new SelectListItem
{
Text = item.CustomerName,
Value = item.CustomerID.ToString(),
Selected = isSelected
});
}
///Need to resolve the issue with request form adding to database.
var servername = "";
if(IsPost){
customerID = Request.Form["Customers"];
servername = Request.Form["ServerName"];
var db2 = Database.Open("BackupMonitoringAppV2");
var insertCommand = "INSERT INTO Servers (CustomersID, Servername,) Values(#0, #1)";
db.Execute(insertCommand, customerID, servername);
Response.Redirect("~/Dashboard/Servers");
}
HTML
<form role="form" method="post">
<div class="form-group">
#Html.DropDownList("Customers", customerdropdowndata)
</div>
<div class="form-group">
<label for="CustomerName">Server Name</label>
<input type="text" class="form-control" name="customername" value="#Request.Form["ServerName"]" />
</div>
<button type="submit" class="btn btn-info" name="buttonSubmit">Add Server</button>
</form>

Tag Helper Select element is empty even though its data source is not

I'm using ASP.NET Core MVC RC2 project using "Database First Model". The database is the famous Northwind database. Everything works fine except that the "Select Tag Helper" (an HTML drop-down list) that is supposed to be populated with the ViewBag data is empty even though the ViewBag data is not empty:
The following action method on the CustomersController correctly displays the list of all customers:
public IActionResult Index()
{
List<Customers> data = repository.SelectAll();
return View("/views/Northwind/Index.cshtml", data);
}
When a user clicks the "Edit" link on a record, the following Edit action correctly displays that record values in Edit form except that the drop-down for countries is empty:
public IActionResult Edit(string id)
{
Customers data = repository.SelectByID(id);
var query = (from c in repository.Context.Customers
orderby c.Country ascending
select new SelectListItem() { Text = c.Country, Value = c.Country }
).Distinct();
List<SelectListItem> countries = query.ToList();
ViewBag.Countries = countries;
return View("/views/Northwind/Edit.cshtml", data);
}
The following is the "view" that displays the editable data except that the drop-down is blank:
#model MVCCoreCR2_Project.Models.Customers
<div class="form-group">
<label asp-for="Country" class="col-md-2 control-label"></label>
<div class="col-md-10">
<select asp-for="Country" asp-items="#ViewBag.Countries" class="form-control" />
<span asp-validation-for="Country" class="text-danger" />
</div>
</div>
Note: During debugging, when I put a break-point at <select asp-for="Country" asp-items="#ViewBag.Countries" class="form-control" /> and hover over #ViewBag.Countries I can see the countries in the ViewBag are filled in.
A <select> is not a self closing tag. It needs to be
<select asp-for="Country" asp-items="ViewBag.Countries" class="form-control"></select>

Passing selected button value from view to controller

I would like to pass the selected button value to the controller. See my code below.
In my controller I am passing through the ProductId which I will then use to set up my product value inside my controller.
Controller:
public ActionResult PlaceOrder(int ProductId, string OrderType)
{
// Do something
}
Inside my view I have a foreach loop which will create radio like buttons and I have also got a hiddenfor(SelectedProductId)
View:
<div class="panel panel-primary">
<div class="panel-heading">Panel Name</div>
<div class="panel-body">
<div class="row">
<div class="form-group">
#Html.HiddenFor(m => m.SelectedProductId)
#if (Model.Products != null && Model.Products.Count > 0)
{
<div class="btn-group" data-toggle="buttons">
#foreach (var product in Model.Products)
{
<label class="btn btn-default productButton">
<div class="labelProduct">#Product.Name</div>
<input type="radio" name="ProductGMX" id="#("product" + #product.Id)" autocomplete="off" checked data-id="#product.Id">
</label>
}
</div>
I will want to pass the Product Id in the ActionLink which will then pass it to the controller but I am not sure how this can be achieved
Button Click:
#Html.ActionLink("Order with standard delivery", "PlaceOrder", "Standard", new { ProductId = ?, OrderType = "Standard delivery" }, new { area = "Standard" })
#Html.ActionLink("Order with Next day Delivery", "PlaceOrder", "Elevated", new { ProductId = ?, OrderType = "NextDay" }, new { area = "Elevated", })
You either need to use JavaScript to update the ActionLink's url whenever the product changes, using the data-id from the radio button.
Or
Use submit buttons instead of ActionLinks, and set the value on the radio button to the product id. You'll need to put some logic in your controller to handle the two different buttons.
Those aren't buttons. They're links, which don't participate in the form submission.
Use real buttons, i.e. <button></button> and give them a name. Then you can see which was clicked by inspecting the Request object:
<button name="_StandardDelivery">Order with standard delivery</button>
Then in your action:
if (Request["_StandardDelivery"] != null) {
// user chose standard delivery
}

Categories

Resources