I am currently being taught how to use MVC and my supervisor showed me how to use a repository with a read function but I'm stuck with implementing an Add function. This is my current code, thanks in advance!
Repository:
public void AddDriver(DriverModel model)
{
using (var db = new VehicleReservationEntities())
{
var newDriver = new Driver();
newDriver.DriverLastName = model.DriverLastName;
newDriver.DriverFirstName = model.DriverFirstName;
newDriver.DriverLicense = model.DriverLicense;
newDriver.LicenseExpiry = model.LicenseExpiry;
newDriver.MobileNumber = model.MobileNumber;
newDriver.BusinessUnit = model.BusinessUnit;
newDriver.DateRegistered = model.DateRegistered;
db.Driver.Add(newDriver);
db.SaveChanges();
}
}
Controller:
public ActionResult Add()
{
var repo = new VehicleRepository();
var data = repo.AddDriver();
var DVM = new DriverViewModel();
DVM.DriverLastName = data.DriverLastName;
DVM.DriverFirstName = data.DriverFirstName;
DVM.DriverLicense = data.DriverLicense;
DVM.LicenseExpiry = data.LicenseExpiry;
DVM.MobileNumber = data.MobileNumber;
DVM.BusinessUnit = data.BusinessUnit;
DVM.DateRegistered = data.DateRegistered;
db.Driver.Add();
db.SaveChanges();
}
There seems to be a few issues with what you've posted. I think you're looking for something like the following:
Controller:
[HttpPost]
public ActonResult Add(DriverViewModel DVM)
{
var repo = new VehicleRepository();
var driver = new Driver();
//tools such as automapper or tinymapper are often used so that you dont
//need to manually make these assignments
driver.DriverLastName = DVM.DriverLastName;
driver.DriverFirstName = DVM.DriverFirstName;
driver.DriverLicense = DVM.DriverLicense;
driver.LicenseExpiry = DVM.LicenseExpiry;
driver.MobileNumber = DVM.MobileNumber;
driver.BusinessUnit = DVM.BusinessUnit;
driver.DateRegistered = DVM.DateRegistered;
repo.AddDriver(driver);
//return whatever view you want to go to after the save
return View("Index");
}
Repository:
public void AddDriver(Driver newDriver)
{
using (var db = new VehicleReservationEntities())
{
db.Driver.Add(newDriver);
db.SaveChanges();
}
}
a few notes: normally, if you're using viewmodels then these viewmodels are posted to the controller instead of the raw EF entities. You were also calling db.SaveChanges in the controller as well as the repository which doesn't seem like what you want. DbSets are also normally pluralized so your call to add the driver to the db would look like db.Drivers.Add(newDriver). You've also shown 3 different classes related to Drivers: Driver, DriverModel and DriverViewModel. Sometimes this is necessary if your architecture has things separated out into multiple different layers for data access, business logic, and web however I don't see any evidence of that here. If everything exists in one project, I'd probably stick to DriverViewModel and Driver where Driver is the EF entity and DriverViewModel is what your views use and pass back to the controller
Related
I'm creating a new customer and adding them to a subscription in one call like so:
StripeConfiguration.SetApiKey(StripeData.ApiKey);
var customerService = new CustomerService();
var myCustomer = new CustomerCreateOptions
{
Email = stripeEmail,
Source = stripeToken,
Plan = StripeData.MonthlySubscriptionPlanId
};
Customer stripeCustomer = customerService.Create(myCustomer);
Then I used to be able to do this:
myLocalUser.StripeCustomerId = stripeCustomer.Id;
myLocalUser.StripeSubscriptionId = stripeCustomer.Subscriptions.Data[0]?.Id;
But now the API isn't returning the customer's subscriptions so the second line fails
I'm now having to call the API again with this ugly code to get the customer's subscriptionId:
if (stripeCustomer.Subscriptions != null)
{
user.StripeSubscriptionId = stripeCustomer.Subscriptions.Data[0]?.Id;
}
else
{
//get subscriptionId
var cust = customerService.Get(stripeCustomer.Id, new CustomerGetOptions
{
Expand = new System.Collections.Generic.List<string> { "subscriptions" }
});
if (cust.Subscriptions.Any())
{
stripeSubscriptionId = cust.Subscriptions.First().Id;
}
}
CustomerService.Create() doesn't have the same Expand parameter option that the Get() method does...
This is expected, as subscriptions are no longer included by default on a customer object unless you expand them since API version 2020-08-27.
Creating a customer with a source and plan is still possible (although not the recommended integration path anymore since you might run into problems with 3DS and tax rates), although since you are on a newer API version you won't get the subscriptions list back. If you can you should update to creating subscriptions via their own API.
If you however still want to use this old integration path, you can still get the subscriptions back in the customer create call, you just need to expand the subscriptions on creation:
var customerService = new CustomerService();
var myCustomer = new CustomerCreateOptions
{
Email = stripeEmail,
Source = stripeToken,
Plan = StripeData.MonthlySubscriptionPlanId
};
myCustomer.AddExpand("subscriptions");
Customer stripeCustomer = customerService.Create(myCustomer);
This is pretty general, but I'm having a hell of a time figuring out how to consume some of the more complicated Sabre APIs.
I have built working .NET proxy classes in C# using the WSDL for the basic APIs (CreateSession, CloseSession) but for the more complicated APIs I have a really hard time parsing out the complicated XML schema to figure out which methods to call in my program.
Are there any other .NET resources/examples out there that aren't wrapped up in MVC like the code example that Sabre posted on GitHub?
I'm trying to figure out how to use APIs like OTA_AirPriceLLSRQ and TravelItineraryReadRQ.
Thanks in advance for any help!
As I mentioned on the comments, you should not focus on the actual MVC wrapping, as you'll be mainly putting stuff in the Model, or actually you'll put this somewhere else and consume it in the model.
Anyway, just for you to have as example, here's a VERY generic BFM (BargianFinderMax) class. With this approach it's required to create an instance, and after calling the Execute method it stores the response in the instance.
I hope it helps.
using BargainFinderMaxRQv310Srvc;
using System;
using System.IO;
namespace ServicesMethods
{
public class BFM_v310
{
private BargainFinderMaxService service;
private OTA_AirLowFareSearchRQ request;
public OTA_AirLowFareSearchRS response;
public BFM_v310(string token, string pcc, string convId, string endpoint)
{
//MessageHeader
MessageHeader mHeader = new MessageHeader();
PartyId[] pId = { new PartyId() };
pId[0].Value = "SWS";
From from = new From();
from.PartyId = pId;
To to = new To();
to.PartyId = pId;
mHeader.Action = "BargainFinderMaxRQ";
mHeader.Service = new Service()
{
Value = mHeader.Action
};
mHeader.ConversationId = convId;
mHeader.CPAId = pcc;
mHeader.From = from;
mHeader.To = to;
mHeader.MessageData = new MessageData()
{
Timestamp = DateTime.UtcNow.ToString()
};
//Security
Security security = new Security();
security.BinarySecurityToken = token;
//Service
service = new BargainFinderMaxService();
service.MessageHeaderValue = mHeader;
service.SecurityValue = security;
service.SoapVersion = System.Web.Services.Protocols.SoapProtocolVersion.Soap11;
service.Url = endpoint;
createRequest(pcc);
}
private void createRequest(string pcc)
{
request = new BargainFinderMaxRQv310Srvc.OTA_AirLowFareSearchRQ();
request.AvailableFlightsOnly = true;
request.Version = "3.1.0";
request.POS = new SourceType[1];
SourceType source = new SourceType();
source.PseudoCityCode = pcc;
source.RequestorID = new UniqueID_Type();
source.RequestorID.ID = "1";
source.RequestorID.Type = "1";
source.RequestorID.CompanyName = new CompanyNameType();
source.RequestorID.CompanyName.Code = "TN";
source.RequestorID.CompanyName.CodeContext = "Context";
request.POS[0] = source;
OTA_AirLowFareSearchRQOriginDestinationInformation originDestination = new OTA_AirLowFareSearchRQOriginDestinationInformation();
originDestination.OriginLocation = new OriginDestinationInformationTypeOriginLocation();
originDestination.OriginLocation.LocationCode = "BCN";
originDestination.DestinationLocation = new OriginDestinationInformationTypeDestinationLocation();
originDestination.DestinationLocation.LocationCode = "MAD";
originDestination.ItemElementName = ItemChoiceType.DepartureDateTime;
originDestination.Item = "2017-09-10T12:00:00";
originDestination.RPH = "1";
request.OriginDestinationInformation = new OTA_AirLowFareSearchRQOriginDestinationInformation[1] { originDestination };
request.TravelerInfoSummary = new TravelerInfoSummaryType()
{
AirTravelerAvail = new TravelerInformationType[1]
};
request.TravelerInfoSummary.AirTravelerAvail[0] = new TravelerInformationType()
{
PassengerTypeQuantity = new PassengerTypeQuantityType[1]
};
PassengerTypeQuantityType passenger = new PassengerTypeQuantityType()
{
Quantity = "1",
Code = "ADT"
};
request.TravelerInfoSummary.AirTravelerAvail[0].PassengerTypeQuantity[0] = passenger;
request.TravelerInfoSummary.PriceRequestInformation = new PriceRequestInformationType();
request.TravelerInfoSummary.PriceRequestInformation.CurrencyCode = "USD";
//PriceRequestInformationTypeNegotiatedFareCode nego = new PriceRequestInformationTypeNegotiatedFareCode();
//nego.Code = "ABC";
//request.TravelerInfoSummary.PriceRequestInformation.Items = new object[1] { nego };
request.TPA_Extensions = new OTA_AirLowFareSearchRQTPA_Extensions();
request.TPA_Extensions.IntelliSellTransaction = new TransactionType();
request.TPA_Extensions.IntelliSellTransaction.RequestType = new TransactionTypeRequestType();
request.TPA_Extensions.IntelliSellTransaction.RequestType.Name = "50ITIN";
}
public bool Execute()
{
response = service.BargainFinderMaxRQ(request);
return response.PricedItinCount > 0;
}
}
}
My advice is you should add separate models which are built based on Sabre models, and which flatten the whole structure.
For example, TravelItineraryReadRS is a quite complicated document. Using it properties in your program is a real "pain", because every time you need to remember the whole path that leads to to specific information (like, "what is passenger type for PersonName of NameNumber 01.01?").
I suggest you have dedicated model (let's name it Reservation), which have all information that you will need later in your application, extracted from TravelItineraryReadRs.
In order to achieve this you need a dedicated converter which will make convert TravelItineraryReadRs model into Reservation model. Now, inside Reservation model you could have list of Passenger models, which have in on place all important information (NameNumber, PassengerType, SSR codes, etc).
This improves readability and as a bonus you decouple your application from Sabre (imagine, one day someone asks "can we switch from Sabre to Amadeus?" - if you use dedicated models the answer is "yes". If you don't have, then the answer is "probably yes, but it will take 6-9 months).
I am trying to learn and build an web application using asp.net MVC 5, WEB API 2 and AngularJS. I have already built up a good working application with custom CRUD operations. Now I want complete control on the web api controller, so that I can return data as per my requirement. For example I want to get the returned data from the following code -
string today = DateTime.Now.ToString("dd/MM/yyyy");
var appointment1 = from prescription in db.Prescriptions
where prescription.appointment == "15/01/2015"
from consultation in prescription.Consultations
select new
{
ID = prescription.id,
Name = prescription.patient_name,
Contact = prescription.patient_contact,
Task = prescription.next_task
};
var appointment2 = from consultation in db.Consultations
where consultation.next_date == "15/01/2015"
select new
{
ID = consultation.Prescription.id,
Name = consultation.Prescription.patient_name,
Contact = consultation.Prescription.patient_contact,
Task = consultation.next_task
};
var finalAppointments = appointment1.Concat(appointment2);
return finalAppointments;
I have three questions:
1) Is there any way to retrieve the returned data other than creating custom methods in my web api controller?
2) Can I just use the default method by modifying it a bit? if so then how?
3) If I SHOULD use a custom method what would be the method structure with returned data type?
Its very simple.
Note: I don't understand your first question properly. for 2que and 3que....
Lets say I'm using Get Method in Web api 2, MVC5 (I hope your are clear with HTTP methods in web api)
Which collects required data (to be returned back to angularjs).....
Now it depends upon your requirement that how many objects you want to send back to client side.
IHttpActionResult would be your return type in all HTTP methods as IHttpActionResult sends Status code via Web api....
eg;
Lets say I have PrescriptionsController.cs. So in it.
[HttpGet]
public IHttpActionResult Get()
{
var appointment1 = from prescription in db.Prescriptions
where prescription.appointment == "15/01/2015"
from consultation in prescription.Consultations
select new
{
ID = prescription.id,
Name = prescription.patient_name,
Contact = prescription.patient_contact,
Task = prescription.next_task
};
var appointment2 = from consultation in db.Consultations
where consultation.next_date == "15/01/2015"
select new
{
ID = consultation.Prescription.id,
Name = consultation.Prescription.patient_name,
Contact = consultation.Prescription.patient_contact,
Task = consultation.next_task
};
var finalAppointments = appointment1.Concat(appointment2);
// return finalAppointments; //rather I'd use below line...
return Ok(finalAppointments); // here your are concatenating two objects and want to send single object only.
}
Lets say I want to send two objects separately...
then use following way,
[HttpGet]
//public IHttpActionResult Get()
public dynamic Get()
{
var appointment1 = from prescription in db.Prescriptions
where prescription.appointment == "15/01/2015"
from consultation in prescription.Consultations
select new
{
ID = prescription.id,
Name = prescription.patient_name,
Contact = prescription.patient_contact,
Task = prescription.next_task
};
var appointment2 = from consultation in db.Consultations
where consultation.next_date == "15/01/2015"
select new
{
ID = consultation.Prescription.id,
Name = consultation.Prescription.patient_name,
Contact = consultation.Prescription.patient_contact,
Task = consultation.next_task
};
//var finalAppointments = appointment1.Concat(appointment2);
// return finalAppointments; //rather I'd use below line...
// return Ok(finalAppointments); // here your are concatenating two objects.
return new {appointment1 ,appointment2 }; // you can send multiple objects...
}
Any query feel free to ask.
I've looked at so many posts about this, but still haven't found the solution:
I'm using a winforms app that uses EntityFramework (6?). When I load the form I can read from the DB using the context (Entities). However, when I savechanges after adding a new entity, it doesn't persist to the db.
var c = new Card { Name = tbName.Text, Quantity = int.Parse(tbQuantity.Text) };
dbContext.Cards.Add(c);
dbContext.SaveChanges();
The dbContext is setup in the form constructor and is an instance of "LiquorTrackEntities".
LiquorTrackEntities dbContext;
public Form1()
{
InitializeComponent();
dbContext = new LiquorTrackEntities()
Reading from the db works:
var cards = dbContext.Cards.ToList();
I do this stuff all the time in asp.net MVC, but it isn't working in WinForms.. is there something special I have to do in winforms? I also know about the normal "using (var db = new LiquorEntitiesEntities())" convention, but I just want to get this functioning before I worry about convention.
Any ideas?
Just tried this to no avail:
var c = new Card { Name = tbName.Text, Quantity = int.Parse(tbQuantity.Text) };
dbContext.Cards.Attach(c);
dbContext.Entry(c).State = EntityState.Added;
dbContext.SaveChanges();
Just tried creating a new EDMX using EF5 instead.. same problem.
UPDATE:
SaveChanges does return a 1 when after adding a card. It stays in the context (if I reload my cards from the context, the new one is there..) but never makes it to the database.
It is necessary that after the creation of records in the table "Clients" took up ID. Later ID used to create a new entry in the "Clients_details".
var user = GetUsers();
var userdet = GetclientsDetails();
string hashedpass = getMd5Hash(UIPassword.Text);
var newreg = new Clients
{
login = UILogin.Text,
password = hashedpass,
subscribeid = Convert.ToInt32(UIId.Text)
};
user.InsertOnSubmit(newreg);
user.Context.SubmitChanges();
var details = new Clients_details
{
city = UICity.Text,
first_name = UIFirst_name.Text,
last_name = UIFamiliya.Text,
name = UIName.Text,
Clients = newreg
};
userdet.InsertOnSubmit(details);
userdet.Context.SubmitChanges();
After this code fails:
"An attempt was made to perform an operation Attach or Add in relation to an object that is not new, and possibly loaded from another DataContext. This operation is not supported."
How to properly create a record that does not appear a mistake? Thank you!
private static Table<Clients> GetUsers()
{
var dce = new BaseDBMLDataContext();
return dce.Clients;
}
private static Table<Clients_details> GetclientsDetails()
{
var dce = new BaseDBMLDataContext();
return dce.Clients_details;
}
Looks like userdet.Context and user.Context was built using a different dataContext and that needs to be created using the same dataContext rather than instantiating a new one.
I think you need to only call the SubmitChanges only once in the end, and also you need to make sure the user and userdet you are using share the same context
As the error clearly states, you're using different contexts (user and userdet) for each entity to add. You should have one DataContext and use that one to add the entities.
Yes looks like you're using two different instances of the same context:
user.Context.SubmitChanges();
userdet.Context.SubmitChanges();
A good approach to build up your entities should be something like :
//Create your client details entity
var details = new Clients_details
{
city = UICity.Text,
first_name = UIFirst_name.Text,
last_name = UIFamiliya.Text,
name = UIName.Text
};
//Create your client entity
var newreg = new Clients
{
login = UILogin.Text,
password = hashedpass,
subscribeid = Convert.ToInt32(UIId.Text),
//Assigning the details entity (FK) to the client
ClientDetails = details
};
//Saving both the client and its details
user.InsertOnSubmit(newreg);
user.Context.SubmitChanges();