ASP MVC Return SP result to View - asp.net-mvc

Using VS 2013 and writing my first ASP MVC app. I have a controller:
// GET: CreateBundlesAndCartons
public ActionResult CreateBandC(Int32 id)
{
string ReturnMessage;
ReturnMessage = "";
using (SqlConnection connection = new SqlConnection())
{
//string connectionStringName = this.DataWorkspace.CooperData.Details.Name;
connection.ConnectionString =
ConfigurationManager.ConnectionStrings["PSAContext"].ConnectionString;
string procedure = "PSA.dbo.CreateBundlesAndCartons";
using (SqlCommand command = new SqlCommand(procedure, connection))
{
command.CommandType = CommandType.StoredProcedure;
command.CommandTimeout = 300;
command.Parameters.Add(
new SqlParameter("#JobID", id));
SqlParameter ErrorString = new SqlParameter("#ErrorString", ReturnMessage);
ErrorString.Direction = ParameterDirection.Output;
ErrorString.Size = 4000;
command.Parameters.Add(ErrorString);
connection.Open();
command.ExecuteNonQuery();
// Save Outout Param
ReturnMessage = ErrorString.Value.ToString();
}
}
return Content("You requested the to create bundles and cartons for job ID " + id.ToString() + "<br />Result: " + ReturnMessage + "<br /> ");
}
I want to display the results to the user and them give them ability to return to the jobs view.
I tried this as my return value:
return Content("You requested the to create bundles and cartons for job ID " + id.ToString() + "Result: " + ReturnMessage + " Return to Jobs");
This displays the results and the link:
But the link points to http://localhost:59971/Jobs/CreateBandC/~/Jobs/ instead of http://localhost:59971/Jobs/
How can I fix that?
Is there a better way to return the results?
I'm under some time pressure, so this approach would do for now, but I'd like to actually figure out how to return a more complex type and nicer view
Thanks
mark

Looks like this requires database changes to fix the link. This is typically a result of poor design and tight coupling. So, go in the database and change the a tag in your stored procedure to get the desired result.

Related

MVC: how to call a non-async method from within a method that has async Task<ActionResult> as the return type

MVC web app calling methods in a MVC web api.
I have an async method which executes another async method - GetMultiSelections(...).
Both call out to a web api.
They work fine.
However, I added in some new code - the foreach after the 1st method - GetMultiSelections(...).
I encountered an error. So I now want to call another web api method to write the error to a log. It's a non-async method that does not return anything as I don't want anything coming back. (or should I?)
I do this in the 1st Catch. It executes the non-async method but does not go into the web api. I step threw it but it never actually goes into the web api method. I have a break point in the web api and it does not get there.
Is the async preventing it? If so, how to I get the non-async to be executed?
In the non-async method and does the call to the web api - just does not get in there:
The api method - it does not get here:
Returned from the non-async method - and throws the error as expected:
The async method which executes another async method. The both do a call to the web api.:
[HttpGet]
public async Task<ActionResult> GetUserProfile()
{
UserProfileForMaintVM userProfileForMaintVM = new UserProfileForMaintVM();
try
{
List<UserProfileHoldMulti> userProfileHoldMulti = new List<UserProfileHoldMulti>();
// Get all the user's multi-selections and the ones he/she did not select.
userProfileHoldMulti = await GetMultiSelections(Session["UserName"].ToString(), Convert.ToInt32(Session["UserId"]));
foreach (var hold in userProfileHoldMulti)
{
switch (hold.ProfileCategoryId)
{
case 25:
// Instantiate a new UserProfileMulti25.
UserProfileMulti25 userProfileMulti25 = new UserProfileMulti25
{
SelectionId = hold.SelectionId,
ProfileCategoryId = hold.ProfileCategoryId,
Description = hold.Description,
SelectedSwitch = hold.SelectedSwitch
};
// Add the multi list to the model's multi list.
userProfileForMaintVM.UserProfileMultiList25.Add(userProfileMulti25);
break;
}
}
}
catch (Exception ex)
{
// Call the web api to process the error.
ProcessClientError(Session["UserName"].ToString(), ex.Message, "From method: GetUserProfile. processing multi-selections");
throw;
}
if ((string)#Session["HasProfileSwitch"] == "False")
{
return View("UserProfileMaint", userProfileForMaintVM);
}
else
{
try
{
string hostName = Dns.GetHostName();
string myIpAddress = Dns.GetHostEntry(hostName).AddressList[2].ToString();
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:56224");
string restOfUrl = "/api/profileandblog/getuserprofile/" + Session["UserName"] + "/" + myIpAddress + "/" + Session["UserId"];
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage result = await client.GetAsync(restOfUrl);
if (result.IsSuccessStatusCode)
{
var userResponse = result.Content.ReadAsStringAsync().Result;
userProfileForMaintVM.UserProfileSingleVM = JsonConvert.DeserializeObject<UserProfileSingleVM>(userResponse);
}
else
{
ViewBag.errormessage = "Server error on getting the active userProflie. UserId: " + Session["UserId"] + ". Method: 'GetUserProfile'. Please contact the administrator.";
}
return View("UserProfileMaint", userProfileForMaintVM);
}
}
catch (Exception)
{
throw;
}
}
}
The non-async method:
public void ProcessClientError(string userName, string errorMessage, string additionalInfo)
{
try
{
string hostName = Dns.GetHostName();
string myIpAddress = Dns.GetHostEntry(hostName).AddressList[2].ToString();
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:56224");
string restOfUrl = "/api/profileandblog/processclienterror/" + Session["UserName"] + "/" + errorMessage + additionalInfo + myIpAddress + "/";
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.GetAsync(restOfUrl);
}
}
catch (Exception)
{
throw;
}
}
GetAsync/PostAsync doesn't necessarily need to call an async method. The GetAsync/PostAsync are the actual async methods wherein once it is called, you have the option to wait for it to finish.
The error I'm seeing is you're calling the webapi with GetAsync but in your screenshot the web method ProcessClientError is [HttpPost].
Change ProcessClientError data annotation to [HttpGet].
Hmm, upon checking again, the url you're trying to access might not match the one you provided in your route. It's missing some slashes /.
your current:
string restOfUrl = "/api/profileandblog/processclienterror/" + Session["UserName"] + "/" + errorMessage + additionalInfo + myIpAddress + "/";
possible fix:
string restOfUrl = "/api/profileandblog/processclienterror/" + Session["UserName"] + "/" + errorMessage + "/" + additionalInfo + "/" + myIpAddress + "/";
If that still doesnt work, try to url encode the parameters with slashes /.
string restOfUrl = "/api/profileandblog/processclienterror/" + Session["UserName"] + "/" + errorMessage + "/" + additionalInfo + "/" + Url.Encode(myIpAddress) + "/";

Oledbcommand with date in the where clause

I am using oledbconnection to read dbf files. I am trying to search all data from a specific dbf database. I am doing it well when there is no date in where clause. But when I am using date as a where I am having zero result.
String constr = #"Provider=VFPOLEDB.1;Data Source=" + Directory.GetParent(cashierPath).FullName +
";Exclusive=false;Nulls=false";
DataTable dt = new DataTable();
OleDbConnection con= new OleDbConnection(constr);
con.Open();
using (OleDbCommand cmd = con.CreateCommand())
{
cmd.CommandText = "select id from " + Path.GetFileName(cashierPath) + " where todate=#todate";
cmd.Parameters.AddRange(new OleDbParameter[]
{
new OleDbParameter("#todate", "2016-07-21")
});
using(OleDbDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
reader.Read();
String data = reader.GetString(0);
MessageBox.Show(data);
}
}
}
I don't really know what the problem.

OleDbConnection - object reference not set to an instance of an object

I have a form an one button on it,
below is very really simple my code:
private void ConnectDb()
{
try
{
connect = new OleDbConnection();
connect.ConnectionString = #"Provider=Microsoft.ACE.OLEDB.15.0;Data Source=MySong.accdb;Persist Security Info=false;";
connect.Open();
statusText.Text = "Database connected";
command = connect.CreateCommand();
}
catch (Exception)
{
statusText.Text = "ERROR::Database failed";
}
}
private void CloseConnectDb()
{
if (connect != null)
{
connect.Close();
statusText.Text = "Database Closed";
}
}
private void btnTambah_Click(object sender, EventArgs e)
{
DateTime tanggal = DateTime.Today;
Band = txtArtis.Text;
Title = txtJudul.Text;
this.ConnectDb();
command.CommandText = "INSERT INTO TableLagu (Tanggal, Artis, Title, Status) VALUES ('" + tanggal + "', '" + Band + "', '" + Title + "', 'Belum ada')";
if (command.ExecuteNonQuery() != 0) //executenonquery returns number of row affected
{
statusText.Text = "ADD--Data Success inserted";
txtArtis.Text = "";
txtJudul.Text = "";
}
else statusText.Text = "ERROR::Insert failed";
this.CloseConnectDb();
}
When i click on my 'btnTambah' button, it always say "object reference not set to an instance of an object" and display "ERROR::Database failed" on its statusText.
any solution??
i think this code doesn't run while try to call ConnectDb method.
you can see my connection string
Provider=Microsoft.ACE.OLEDB.15.0;
actually, when i creating it, i have microsoft access database 2013 installed on my machine. it works good.
now, i'm trying to run my application on my friends computer that microsoft access installed version 2007. and got an error like above.

Parse IMAP message and extract header information

I am trying to extract header and body information from email, the following code retrieves the header and body in their raw form. I have an email object that contains the fields from, subject, date, and body. I would like to extract these values from the email and assign them to the email object. How do I get around it? I have tried several ways like getting the header info and using a streamReader.ReadLine() to get a line but I got illegal path exceptions. I know I can use a library but I need to achieve it this way.
What I mean is this, IMAP command returns header information. And I want to extract subject value, date value, sender e-amil, etc. and assign them to my email objects corresponding values like
emailObject.subject = "subjectValue"
public class Imap
{
static void Main(string[] args)
{
try
{
path = Environment.CurrentDirectory + "\\emailresponse.txt";
if (System.IO.File.Exists(path))
System.IO.File.Delete(path);
sw = new System.IO.StreamWriter(System.IO.File.Create(path));
tcpc = new System.Net.Sockets.TcpClient("imap.gmail.com", 993);
ssl = new System.Net.Security.SslStream(tcpc.GetStream());
ssl.AuthenticateAsClient("imap.gmail.com");
receiveResponse("");
Console.WriteLine("username : ");
username = Console.ReadLine();
Console.WriteLine("password : ");
password = Console.ReadLine();
receiveResponse("$ LOGIN " + username + " " + password + " \r\n");
Console.Clear();
receiveResponse("$ LIST " + "\"\"" + " \"*\"" + "\r\n");
receiveResponse("$ SELECT INBOX\r\n");
receiveResponse("$ STATUS INBOX (MESSAGES)\r\n");
Console.WriteLine("enter the email number to fetch :");
int number = int.Parse(Console.ReadLine());
Console.WriteLine("*************Header************");
Console.WriteLine("");
// receiveResponse("$ FETCH " + number + " body[header]\r\n");
// BODY.PEEK[HEADER.FIELDS (SUBJECT)]
// StringBuilder sb = receiveResponse("$ FETCH " + number + " BODY.PEEK[HEADER.FIELDS (From Subject Date)]\r\n");
StringBuilder sb= receiveResponse("$ FETCH " + number + " body.peek[header]\r\n");
Console.WriteLine(sb);
Console.WriteLine("");
Console.WriteLine("Body");
sb = new StringBuilder();
sb=receiveResponse("$ FETCH " + number + " body[text]\r\n");
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
byte[] serverbuff = new Byte[1024];
int count = 0;
string retval = enc.GetString(serverbuff, 0, count);
Console.WriteLine(sb.ToString());
receiveResponse("$ LOGOUT\r\n");
}
catch (Exception ex)
{
Console.WriteLine("error: " + ex.Message);
}
finally
{
if (sw != null)
{
sw.Close();
sw.Dispose();
}
if (ssl != null)
{
ssl.Close();
ssl.Dispose();
}
if (tcpc != null)
{
tcpc.Close();
}
}
Console.ReadKey();
}
static StringBuilder receiveResponse(string command)
{
sb = new StringBuilder();
try
{
if (command != "")
{
if (tcpc.Connected)
{
dummy = Encoding.ASCII.GetBytes(command);
ssl.Write(dummy, 0, dummy.Length);
}
else
{
throw new ApplicationException("TCP CONNECTION DISCONNECTED");
}
}
ssl.Flush();
buffer = new byte[2048];
bytes = ssl.Read(buffer, 0, 2048);
sb.Append(Encoding.ASCII.GetString(buffer));
// Console.WriteLine(sb.ToString());
sw.WriteLine(sb.ToString());
// sb = new StringBuilder();
return sb;
}
catch (Exception ex)
{
throw new ApplicationException(ex.Message);
}
}
You said you do not want to use an IMAP library. This means that you will have to implement your own. You should start by reading RFC 3501 because there is no chance you could get the protocol right without reading the docs carefuly. In particular, you're issuing a STATUS command on the currently selected mailbox, which is explicitly forbidden by the protocol specification. The rest of the code supports the assumption that you have not read the RFC yet.

ASP.NET MVC 4 Redirecting back to Index view

Off the bat: I am new to using asp.net mvc 4.
I am have a action that creates a excel file and then converts it to PDF.
From View
#Html.ActionLink("Generate Invoice", "genInvoice", new { id = item.invoiceID }) |
Action:
public ActionResult genInvoice(int id = 0)
{
var invoiceItems = from k in db.InvoiceItems
where k.invoiceID == id
select k;
string invoiceClient = (from kk in db.Invoices
where kk.invoiceID == id
select kk.clientName).Single();
invoiceClient = invoiceClient + "_" + DateTime.Now.ToString("ddd dd MMM yyyy hhTmm");
string websitePath = Request.PhysicalApplicationPath;
string pathName = websitePath + "\\" + invoiceClient ;
generateInvoice(invoiceItems, pathName + ".xlsx", id);
convertToPDF(pathName, invoiceClient);
//Response.AppendHeader("Content-Disposition", "attachment");
var viewModel = new InvoiceItemAdd();
viewModel.Invoices = db.Invoices
.Include(i => i.InvoiceItems)
.OrderBy(i => i.invoiceID);
return View("Index", viewModel);
//return RedirectToAction("Index",viewModel);
}
Now I want to to eventually download the PDF file and then return to the index view.
It goes to the Index view prints the html etc etc but then the window stays as a white screen with the url: /Invoice/genInvoice/1
Any idea how I can go about doing this? (Going back to the Index view after PDF generation, also downloading it)
I am sorry, I fixed the white screen problem. While attempting to do the PDF download
//Response.AppendHeader("Content-Disposition", "inline; filename="+invoiceClient+".pdf");
//Return File(output, "application/pdf");
//Response.Flush();
//Response.End();
Response.End() was not commented out and that stopped it I guess.
Now the problem is how to open the PDF in a separate tab and return to index in the current
with the above code.
EDIT:
Decided the file can just be downloaded.
public FileResult genInvoice(int id = 0)
{
//More code
Response.AppendHeader("Content-Disposition", "attachment; filename="+pathName+".pdf");
return File(websitePath + "\\" + invoiceClient + ".pdf", "application/pdf");
}

Resources