How to save Rotativa PDF on server - asp.net-mvc-5

I am using Rotativa to generate PDF in my "MVC" application. How can I save Rotativa PDF? I need to save the document on a server after all the process is completed.
Code below:
public ActionResult PRVRequestPdf(string refnum,string emid)
{
var prv = functions.getprvrequest(refnum, emid);
return View(prv);
}
public ActionResult PDFPRVRequest()
{
var prv = Session["PRV"] as PRVRequestModel;
byte[] pdfByteArray = Rotativa.WkhtmltopdfDriver.ConvertHtml("Rotativa", "Approver", "PRVRequestPdf");
return new Rotativa.ViewAsPdf("PRVRequestPdf", new { refnum = prv.rheader.request.Referenceno });
}

You can give this a try
var actionResult = new ActionAsPdf("PRVRequestPdf", new { refnum = prv.rheader.request.Referenceno, emid = "Whatever this is" });
var byteArray = actionResult.BuildPdf(ControllerContext);
var fileStream = new FileStream(fullPath, FileMode.Create, FileAccess.Write);
fileStream.Write(byteArray, 0, byteArray.Length);
fileStream.Close();
If that doesn't do the trick then, you can follow the answers here
Just make sure if you do it this way not to have PRVRequestPdf return as a PDF View, rather a normal View like you have above (only mention as managed to fall foul of that myself causing lots of fun).

Another useful answer:
I found the solution here
var actionPDF = new Rotativa.ActionAsPdf("YOUR_ACTION_Method", new { id = ID, lang = strLang } //some route values)
{
//FileName = "TestView.pdf",
PageSize = Size.A4,
PageOrientation = Rotativa.Options.Orientation.Landscape,
PageMargins = { Left = 1, Right = 1 }
};
byte[] applicationPDFData = actionPDF.BuildPdf(ControllerContext);
This is the original thread

You can achieve this with ViewAsPdf.
[HttpGet]
public ActionResult SaveAsPdf(string refnum, string emid)
{
try
{
var prv = functions.getprvrequest(refnum, emid);
ViewAsPdf pdf = new Rotativa.ViewAsPdf("PRVRequestPdf", prv)
{
FileName = "Test.pdf",
CustomSwitches = "--page-offset 0 --footer-center [page] --footer-font-size 8"
};
byte[] pdfData = pdf.BuildFile(ControllerContext);
string fullPath = #"\\server\network\path\pdfs\" + pdf.FileName;
using (var fileStream = new FileStream(fullPath, FileMode.Create, FileAccess.Write))
{
fileStream.Write(pdfData, 0, pdfData.Length);
}
return Json(new { isSuccessful = true }, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
//TODO: ADD LOGGING
return Json(new { isSuccessful = false, error = "Uh oh!" }, JsonRequestBehavior.AllowGet);
//throw;
}
}

You can simply try this:
var fileName = string.Format("my_file_{0}.pdf", id);
var path = Server.MapPath("~/App_Data/" + fileName);
System.IO.File.WriteAllBytes(path, pdfByteArray );

Related

Xamarin.iOS Cannot display photo in Push Notification

I have a Notification Service Extension and an AppGroup. I save a photo from camera in the PCL project and copy it to the App Group Container (shared folder).
In the Notification Service Extension I try to download the photo from the App Group container and attach it to the notification but it just does not display in the notification.
I also cannot debug the Service Extension to see what is going. As far as I know that is not possible currently still in Xamarin unless someone can correct me on that please.
Here is the code:
1.in my PCL I save the photo to the AppGroup when a save button is pressed:
private void ButtonSavePhoto_Clicked(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(photoFilePath))
{
Preferences.Set(AppConstants.CUSTOM_PICTURE_FILE_PATH, photoFilePath);
Preferences.Set(AppConstants.CUSTOM_PHOTO_SET_KEY, true);
if (Device.RuntimePlatform == Device.iOS)
{
bool copiedSuccessfully = DependencyService.Get<IPhotoService>().CopiedFileToAppGroupContainer(photoFilePath);
if (copiedSuccessfully)
{
var customPhotoDestPath = DependencyService.Get<IPhotoService>().GetAppContainerCustomPhotoFilePath();
// save the path of the custom photo in the AppGroup container to pass to Notif Extension Service
DependencyService.Get<IGroupUserPrefs>().SetStringValueForKey("imageAbsoluteString", customPhotoDestPath);
// condition whether to use custom photo in push notification
DependencyService.Get<IGroupUserPrefs>().SetBoolValueForKey("isCustomPhotoSet", true);
}
}
buttonSavePhoto.IsEnabled = false;
}
}
2.in my iOS project, Dependency injection calls this method when pressing save button:
public bool CopiedFileToAppGroupContainer(string filePath)
{
bool success = false;
string suiteName = "group.com.company.appName";
var appGroupContainerUrl = NSFileManager.DefaultManager.GetContainerUrl(suiteName);
var appGroupContainerPath = appGroupContainerUrl.Path;
var directoryNameInAppGroupContainer = Path.Combine(appGroupContainerPath, "Pictures");
var filenameDestPath = Path.Combine(directoryNameInAppGroupContainer, AppConstants.CUSTOM_PHOTO_FILENAME);
try
{
Directory.CreateDirectory(directoryNameInAppGroupContainer);
if (File.Exists(filenameDestPath))
{
File.Delete(filenameDestPath);
}
File.Copy(filePath, filenameDestPath);
success = true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return success;
}
Now the path for the photo in the App Group container is:
/private/var/mobile/Containers/Shared/AppGroup/12F209B9-05E9-470C-9C9F-AA959D940302/Pictures/customphoto.jpg
3.Finally in the Notification Service Extension I try to attach the photo to the push notification:
public override void DidReceiveNotificationRequest(UNNotificationRequest request, Action<UNNotificationContent> contentHandler)
{
ContentHandler = contentHandler;
BestAttemptContent = (UNMutableNotificationContent)request.Content.MutableCopy();
string imgPath;
NSUrl imgUrl;
string notificationBody = BestAttemptContent.Body;
string notifBodyInfo = "unknown";
string suiteName = "group.com.company.appname";
NSUserDefaults groupUserDefaults = new NSUserDefaults(suiteName, NSUserDefaultsType.SuiteName);
string pref1_value = groupUserDefaults.StringForKey("user_preference1");
string[] notificationBodySplitAtDelimiterArray = notificationBody.Split(',');
userPrefRegion = notificationBodySplitAtDelimiterArray[0];
bool isCustomAlertSet = groupUserDefaults.BoolForKey("isCustomAlert");
bool isCustomPhotoSet = groupUserDefaults.BoolForKey("isCustomPhotoSet");
string alarmPath = isCustomAlertSet == true ? "customalert.wav" : "default_alert.m4a";
if (isCustomPhotoSet)
{
// this is the App Group url of the custom photo saved in PCL
imgPath = groupUserDefaults.StringForKey("imageAbsoluteString");
}
else
{
imgPath = null;
}
if (imgPath != null )
{
imgUrl = NSUrl.FromString(imgPath);
}
else
{
imgUrl = null;
}
if (!string.IsNullOrEmpty(pref1_value))
{
if (BestAttemptContent.Body.Contains(pref1_value))
{
if (imgUrl != null)
{
// download the image from the AppGroup Container
var task = NSUrlSession.SharedSession.CreateDownloadTask(imgUrl, (tempFile, response, error) =>
{
if (error != null)
{
ContentHandler(BestAttemptContent);
return;
}
if (tempFile == null)
{
ContentHandler(BestAttemptContent);
return;
}
var cache = NSSearchPath.GetDirectories(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomain.User, true);
var cachesFolder = cache[0];
var guid = NSProcessInfo.ProcessInfo.GloballyUniqueString;
var fileName = guid + "customphoto.jpg";
var cacheFile = cachesFolder + fileName;
var attachmentUrl = NSUrl.CreateFileUrl(cacheFile, false, null);
NSError err = null;
NSFileManager.DefaultManager.Copy(tempFile, attachmentUrl, out err);
if (err != null)
{
ContentHandler(BestAttemptContent);
return;
}
UNNotificationAttachmentOptions options = null;
var attachment = UNNotificationAttachment.FromIdentifier("image", attachmentUrl, options, out err);
if (attachment != null)
{
BestAttemptContent.Attachments = new UNNotificationAttachment[] { attachment };
}
});
task.Resume();
}
BestAttemptContent.Title = "My Custom Title";
BestAttemptContent.Subtitle = "My Custom Subtitle";
BestAttemptContent.Body = "Notification Body";
BestAttemptContent.Sound = UNNotificationSound.GetSound(alarmPath);
}
}
else
{
pref1_value = "error getting extracting user pref";
}
// finally display customized notification
ContentHandler(BestAttemptContent);
}
/private/var/mobile/Containers/Shared/AppGroup/12F209B9-05E9-470C-9C9F-AA959D940302/Pictures/customphoto.jpg
From shared code, when image getting from AppGroup .You can check the file path whether work in this project.
imgPath = groupUserDefaults.StringForKey("imageAbsoluteString");
If not getting file from this path. You can get Url from AppGroup directly.Here is a sample as follow:
var FileManager = new NSFileManager();
var appGroupContainer = FileManager.GetContainerUrl("group.com.company.appName");
NSUrl fileURL = appGroupContainer.Append("customphoto.jpg", false);
And if fileURL can not be directly used, also can convert to NSData and save to local file system. This also can be a try.
Here is a sample below that grabs from local file system:
public static void Sendlocalnotification()
{
var localURL = "...";
NSUrl url = NSUrl.FromString(localURL) ;
var attachmentID = "image";
var options = new UNNotificationAttachmentOptions();
NSError error;
var attachment = UNNotificationAttachment.FromIdentifier(attachmentID, url, options,out error);
var content = new UNMutableNotificationContent();
content.Attachments = new UNNotificationAttachment[] { attachment };
content.Title = "Good Morning ~";
content.Subtitle = "Pull this notification ";
content.Body = "reply some message-BY Ann";
content.CategoryIdentifier = "message";
var trigger1 = UNTimeIntervalNotificationTrigger.CreateTrigger(0.1, false);
var requestID = "messageRequest";
var request = UNNotificationRequest.FromIdentifier(requestID, content, trigger1);
UNUserNotificationCenter.Current.AddNotificationRequest(request, (err) =>
{
if (err != null)
{
Console.Write("Notification Error");
}
});
}

Get posted file over HTTP Listener in c#

I have make a simple http server using c#. And I know how to get posted data and output them. Here is my c# code
public static void start(){
HttpListener listener = new HttpListener();
listener.Prefixes.Add(new Uri("http://localhost:8080").ToString());
istener.Start();
while(true){
HttpListenerContext con = listener.GetContext();
showPostedData(con.Request);
con.Response.StatusCode = (int)HttpStatusCode.NotFound;
string data = "Uploaded successful";
byte[] output = Encoding.ASCII.GetBytes(data);
con.Response.ContentType = "text/html";
con.Response.ContentLength64 = output.Length;
con.Response.OutputStream.Write(output , 0, output.Length );
}
}
public static void showPostedData(HttpListenerRequest request){
if (!request.HasEntityBody)
{
return;
}
System.IO.Stream body = request.InputStream;
System.Text.Encoding encoding = request.ContentEncoding;
System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding);
string text;
if (request.ContentType != null)
{
text = reader.ReadToEnd();
}
Console.WriteLine( text );
}
My client html form has input box named file: <input type="file" name"file">
In the console output is like that :
file='Path of Choosed file not a file'
So How i get POSTED files and copy them to upload directory..?
Sorry for my english and thanks in advance...
public static void start(){
HttpListener listener = new HttpListener();
listener.Prefixes.Add(new Uri("http://localhost:80").ToString());
istener.Start();
while(true){
HttpListenerContext con = listener.GetContext();
var values = new HttpNameValueCollection(ref con);
try
{
Console.WriteLine(values.Files["file"].FileName);
File.WriteAllText(values.Files["file"].FileName, values.Files["file"].FileData, Encoding.Default);
}
catch (Exception tr)
{
}
}
}
class HTTPFormData
{
public class File
{
private string _fileName;
public string FileName { get { return _fileName ?? (_fileName = ""); } set { _fileName = value; } }
private string _fileData;
public string FileData { get { return _fileData ?? (_fileName = ""); } set { _fileData = value; } }
private string _contentType;
public string ContentType { get { return _contentType ?? (_contentType = ""); } set { _contentType = value; } }
}
private NameValueCollection _post;
private Dictionary<string, File> _files;
private readonly HttpListenerContext _ctx;
public NameValueCollection Post { get { return _post ?? (_post = new NameValueCollection()); } set { _post = value; } }
public NameValueCollection Get { get { return _ctx.Request.QueryString; } }
public Dictionary<string, File> Files { get { return _files ?? (_files = new Dictionary<string, File>()); } set { _files = value; } }
private void PopulatePostMultiPart(string post_string)
{
var boundary_index = _ctx.Request.ContentType.IndexOf("boundary=") + 9;
var boundary = _ctx.Request.ContentType.Substring(boundary_index, _ctx.Request.ContentType.Length - boundary_index);
var upper_bound = post_string.Length - 4;
if (post_string.Substring(2, boundary.Length) != boundary)
throw (new InvalidDataException());
var current_string = new StringBuilder();
for (var x = 4 + boundary.Length; x < upper_bound; ++x)
{
if (post_string.Substring(x, boundary.Length) == boundary)
{
x += boundary.Length + 1;
var post_variable_string = current_string.Remove(current_string.Length - 4, 4).ToString();
var end_of_header = post_variable_string.IndexOf("\r\n\r\n");
if (end_of_header == -1) throw (new InvalidDataException());
var filename_index = post_variable_string.IndexOf("filename=\"", 0, end_of_header);
var filename_starts = filename_index + 10;
var content_type_starts = post_variable_string.IndexOf("Content-Type: ", 0, end_of_header) + 14;
var name_starts = post_variable_string.IndexOf("name=\"") + 6;
var data_starts = end_of_header + 4;
if (filename_index != -1)
{
var filename = post_variable_string.Substring(filename_starts, post_variable_string.IndexOf("\"", filename_starts) - filename_starts);
var content_type = post_variable_string.Substring(content_type_starts, post_variable_string.IndexOf("\r\n", content_type_starts) - content_type_starts);
var file_data = post_variable_string.Substring(data_starts, post_variable_string.Length - data_starts);
var name = post_variable_string.Substring(name_starts, post_variable_string.IndexOf("\"", name_starts) - name_starts);
Files.Add(name, new File() { FileName = filename, ContentType = content_type, FileData = file_data });
}
else
{
var name = post_variable_string.Substring(name_starts, post_variable_string.IndexOf("\"", name_starts) - name_starts);
var value = post_variable_string.Substring(data_starts, post_variable_string.Length - data_starts);
Post.Add(name, value);
}
current_string.Clear();
continue;
}
current_string.Append(post_string[x]);
}
}
private void PopulatePost()
{
if (_ctx.Request.HttpMethod != "POST" || _ctx.Request.ContentType == null) return;
var post_string = new StreamReader(_ctx.Request.InputStream, _ctx.Request.ContentEncoding).ReadToEnd();
if (_ctx.Request.ContentType.StartsWith("multipart/form-data"))
PopulatePostMultiPart(post_string);
}
public HTTPFormData(ref HttpListenerContext ctx)
{
_ctx = ctx;
PopulatePost();
}
}

NetSuite SuiteTalk API - Get Inventory Details

I'm using the SuiteTalk (API) service for NetSuite to retrieve a list of Assemblies. I need to load the InventoryDetails fields on the results to view the serial/lot numbers assigned to the items. This is the current code that I'm using, but the results still show those fields to come back as NULL, although I can see the other fields for the AssemblyBuild object. How do I get the inventory details (serials/lot#'s) to return on a transaction search?
public static List<AssemblyBuildResult> Get()
{
var listAssemblyBuilds = new List<AssemblyBuildResult>();
var service = Service.Context();
var ts = new TransactionSearch();
var tsb = new TransactionSearchBasic();
var sfType = new SearchEnumMultiSelectField
{
#operator = SearchEnumMultiSelectFieldOperator.anyOf,
operatorSpecified = true,
searchValue = new string[] { "_assemblyBuild" }
};
tsb.type = sfType;
ts.basic = tsb;
ts.inventoryDetailJoin = new InventoryDetailSearchBasic();
// perform the search
var response = service.search(ts);
response.pageSizeSpecified = true;
// Process response
if (response.status.isSuccess)
{
// Process the records returned in the response
// Get more records with pagination
if (response.totalRecords > 0)
{
for (var x = 1; x <= response.totalPages; x++)
{
var records = response.recordList;
foreach (var t in records)
{
var ab = (AssemblyBuild) t;
listAssemblyBuilds.Add(GetAssemblyBuildsResult(ab));
}
if (response.pageIndex < response.totalPages)
{
response = service.searchMoreWithId(response.searchId, x + 1);
}
}
}
}
// Parse and return NetSuite WorkOrder into assembly WorkOrderResult list
return listAssemblyBuilds;
}
After much pain and suffering, I was able to solve this problem with the following code:
/// <summary>
/// Returns List of AssemblyBuilds from NetSuite
/// </summary>
/// <returns></returns>
public static List<AssemblyBuildResult> Get(string id = "", bool getDetails = false)
{
// Object to populate and return results
var listAssemblyBuilds = new List<AssemblyBuildResult>();
// Initiate Service and SavedSearch (TransactionSearchAdvanced)
var service = Service.Context();
var tsa = new TransactionSearchAdvanced
{
savedSearchScriptId = "customsearch_web_assemblysearchmainlist"
};
// Filter by ID if specified
if (id != "")
{
tsa.criteria = new TransactionSearch()
{
basic = new TransactionSearchBasic()
{
internalId = new SearchMultiSelectField
{
#operator = SearchMultiSelectFieldOperator.anyOf,
operatorSpecified = true,
searchValue = new[] {
new RecordRef() {
type = RecordType.assemblyBuild,
typeSpecified = true,
internalId = id
}
}
}
}
};
}
// Construct custom columns to return
var tsr = new TransactionSearchRow();
var tsrb = new TransactionSearchRowBasic();
var orderIdCols = new SearchColumnSelectField[1];
var orderIdCol = new SearchColumnSelectField();
orderIdCols[0] = orderIdCol;
tsrb.internalId = orderIdCols;
var tranDateCols = new SearchColumnDateField[1];
var tranDateCol = new SearchColumnDateField();
tranDateCols[0] = tranDateCol;
tsrb.tranDate = tranDateCols;
var serialNumberCols = new SearchColumnStringField[1];
var serialNumberCol = new SearchColumnStringField();
serialNumberCols[0] = serialNumberCol;
tsrb.serialNumbers = serialNumberCols;
// Perform the Search
tsr.basic = tsrb;
tsa.columns = tsr;
var response = service.search(tsa);
// Process response
if (response.status.isSuccess)
{
var searchRows = response.searchRowList;
if (searchRows != null && searchRows.Length >= 1)
{
foreach (SearchRow t in searchRows)
{
var transactionRow = (TransactionSearchRow)t;
listAssemblyBuilds.Add(GetAssemblyBuildsResult(transactionRow, getDetails));
}
}
}
// Parse and return NetSuite WorkOrder into assembly WorkOrderResult list
return listAssemblyBuilds;
}
private static string GetAssemblyBuildLotNumbers(string id)
{
var service = Service.Context();
var serialNumbers = "";
var tsa = new TransactionSearchAdvanced
{
savedSearchScriptId = "customsearch_web_assemblysearchlineitems"
};
service.searchPreferences = new SearchPreferences { bodyFieldsOnly = false };
tsa.criteria = new TransactionSearch()
{
basic = new TransactionSearchBasic()
{
internalId = new SearchMultiSelectField
{
#operator = SearchMultiSelectFieldOperator.anyOf,
operatorSpecified = true,
searchValue = new[] {
new RecordRef() {
type = RecordType.assemblyBuild,
typeSpecified = true,
internalId = id
}
}
}
}
};
// Construct custom columns to return
var tsr = new TransactionSearchRow();
var tsrb = new TransactionSearchRowBasic();
var orderIdCols = new SearchColumnSelectField[1];
var orderIdCol = new SearchColumnSelectField();
orderIdCols[0] = orderIdCol;
tsrb.internalId = orderIdCols;
var serialNumberCols = new SearchColumnStringField[1];
var serialNumberCol = new SearchColumnStringField();
serialNumberCols[0] = serialNumberCol;
tsrb.serialNumbers = serialNumberCols;
tsr.basic = tsrb;
tsa.columns = tsr;
var response = service.search(tsa);
if (response.status.isSuccess)
{
var searchRows = response.searchRowList;
if (searchRows != null && searchRows.Length >= 1)
{
foreach (SearchRow t in searchRows)
{
var transactionRow = (TransactionSearchRow)t;
if (transactionRow.basic.serialNumbers != null)
{
return transactionRow.basic.serialNumbers[0].searchValue;
}
}
}
}
return serialNumbers;
}
private static AssemblyBuildResult GetAssemblyBuildsResult(TransactionSearchRow tsr, bool getDetails)
{
if (tsr != null)
{
var assemblyInfo = new AssemblyBuildResult
{
NetSuiteId = tsr.basic.internalId[0].searchValue.internalId,
ManufacturedDate = tsr.basic.tranDate[0].searchValue,
SerialNumbers = tsr.basic.serialNumbers[0].searchValue
};
// If selected, this will do additional NetSuite queries to get detailed data (slower)
if (getDetails)
{
// Look up Lot Number
assemblyInfo.LotNumber = GetAssemblyBuildLotNumbers(tsr.basic.internalId[0].searchValue.internalId);
}
return assemblyInfo;
}
return null;
}
What I learned about pulling data from NetSuite:
Using SavedSearches is the best method to pull data that doesn't automatically come through in the API objects
It is barely supported
Don't specify an ID on the SavedSearch, specify a criteria in the TransactionSearch to get one record
You will need to specify which columns to actually pull down. NetSuite doesn't just send you the data from a SavedSearch automatically
You cannot view data in a SavedSearch that contains a Grouping
In the Saved Search, use the Criteria Main Line = true/false to read data from the main record (top of UI screen), and line items (bottom of screen)

running stored procedures into own model with servicestack ormlite

Is there any examples to be found for running a stored procedure on serviceStack MVC using ormlite? mythz ? seen this block of code:
var results = new List<EnergyCompare>
{dbFactory.Exec(dbCmd =>
{
dbCmd.CommandType = CommandType.StoredProcedure;
dbCmd.Parameters.Add(new SqlParameter("#id", 1));
dbCmd.CommandText = "GetAuthorById";
return dbCmd.ExecuteReader().ConvertTo<EnergyCompare>();
}
)};
but came with the text of never worked on the google groups!
i can also write this:
using(var db = new SwitchWizardDb())
{
var results2 = db.dbCmd.ExecuteProcedure()
}
but not sure how to complete this with parameters, and in the source code I looked at, it said obsolete?
thanks
Looks like ServiceStack.ORMLite has been updated to make this easier:
List<Poco> results = db.SqlList<Poco>("EXEC GetAnalyticsForWeek 1");
List<Poco> results = db.SqlList<Poco>("EXEC GetAnalyticsForWeek #weekNo", new { weekNo = 1 });
List<int> results = db.SqlList<int>("EXEC GetTotalsForWeek 1");
List<int> results = db.SqlList<int>("EXEC GetTotalsForWeek #weekNo", new { weekNo = 1 });
This example is on the front page of the github repo.
Well I figured it was best to roll my own handler so have created this, any thoughts would be most welcome, especially with how I could pass over params in some kind of func or something:
I have a main class to deal with easy access to my connection object:
public class DatabaseNameSp : IDisposable
{
private readonly SqlConnection _spConn = new SqlConnection(DatabaseNameSp .dbConString);
public readonly SqlCommand SpCmd;
public DatabaseNameSp (string procedureName)
{
_spConn.Open();
SpCmd = new SqlCommand
{
Connection = _spConn,
CommandType = CommandType.StoredProcedure,
CommandText = procedureName
};
}
public void Dispose()
{
_spConn.Close();
SpCmd.Dispose();
}
}
usage:
using (var db = new DatabaseNameSp ("procedurenname"))
{
db.SpCmd.Parameters.Add(new SqlParameter("#Id", 1));
var rdr = db.SpCmd.ExecuteReader(CommandBehavior.CloseConnection);
var results = new List<CustomDTO>();
while (rdr.Read())
{
results.Add(new CustomDTO { Name = rdr["name"].ToString(), Id = rdr["id"].ToString() });
}
return new CustomDTOResponse { Results = results };
}
Any thoughts !
thanks
Here is an example of running a stored procedure with ormLite that may help you:
IList<MyDTO> myList = DbFactory.Run(dbCnx =>
{
using (var dbCmd = dbCnx.CreateCommand())
{
dbCmd.CommandType = CommandType.StoredProcedure;
dbCmd.CommandText = "mySchema.myStoredProc";
dbCmd.Parameters.Add(new SqlParameter("#param1", val1));
dbCmd.Parameters.Add(new SqlParameter("#param2", val2));
var r = dbCmd.ExecuteReader();
return r.ConvertToList<MyDTO>();
}
});
To just simply run a stored procedure with no data returned:
public class ComsManager : Dbase
{
private IDbConnection dbConn;
public ComsManager()
{
dbConn = Dbase.GetConnection();
}
public void Housekeeping()
{
using(var dbCmd = dbConn.CreateCommand())
dbConn.Exec(res => { dbCmd.CommandType = CommandType.StoredProcedure; dbCmd.CommandText = "SP_housekeeping"; dbCmd.ExecuteNonQuery(); });
}

How to Mock Subsonic ExecuteReader method?

I have a method that calls stored procedure and returns the data after executing DataReader.
I am trying to test the method using mock. I am not sure how to return value?
Anyone did this? Appreciate your responses.
Here is my code:
// Call the StoredProcedure
public List<string> GetCompletedBatchList(int fileId)
{
List<string> completedBatches = new List<string>();
StoredProcedure sp = new StoredProcedure("GetDistributedBatches", this.dataProvider);
sp.Command.AddParameter("FileID", fileId, DbType.Int32, ParameterDirection.Input);
sp.Command.AddParameter("Result", null, DbType.Int32, ParameterDirection.InputOutput);
using (var rdr = sp.ExecuteReader())
{
while (rdr != null && rdr.Read())
{
if (rdr[0] != null)
{
completedBatches.Add(rdr[0].ToString());
}
}
}
return completedBatches;
}
Here is the Test Method:
[Test]
public void Can_get_completedBatches()
{
var file = new File() { FileID = 1, DepositDate = DateTime.Now };
repo.Add<File>(file);
CompletedBatches completedBatches = new CompletedBatches(provider.Object);
//Here I am not sure how to Return
provider.Setup(**x => x.ExecuteReader(It.IsAny<QueryCommand>())).Returns** =>
{
cmd.OutputValues.Add(0);
});
var completedBatchesList = completedBatches.GetCompletedBatchList(file.FileID);
Assert.AreEqual(0, completedBatchesList.Count());
}
If you want to create a DataReader of a certain shape and size then I suggest you look at DataTable.CreateDataReader DataTable.CreateDataReader. You can then setup the ExecuteReader in your example to return this datareader.
The following link helped me...
How to mock an SqlDataReader using Moq - Update
I used MockDbDataReader method to mock the data
[Test]
public void Can_get_completedBatches_return_single_batch()
{
var date = DateTime.Now;
var file = new File() { FileID = 202, DepositDate = DateTime.Now };
var batch1 = new Batch() { FileID = 202, BatchID = 1767, LockboxNumber = "1", IsLocked = true, LockedBy = "testUser" };
var transaction1 = new Transaction() { BatchID = 1767, TransactionID = 63423, CheckAmount = 100.0 };
var distribution1 = new Distribution() { TransactionID = 63423, InvoiceNumber = "001", Amount = 100.0, DateCreated = date, DateModified = date, TransType = 2 };
repo.Add<File>(file);
repo.Add<Batch>(batch1);
repo.Add<Transaction>(transaction1);
repo.Add<Distribution>(distribution1);
CompletedBatches completedBatches = new CompletedBatches(provider.Object);
provider.Setup(x => x.ExecuteReader(It.IsAny<QueryCommand>())).Returns(MockDbDataReader());
var completedBatchesList = completedBatches.GetCompletedBatchList(202);
Assert.AreEqual(1, completedBatchesList.Count());
}
// You should pass here a list of test items, their data
// will be returned by IDataReader
private DbDataReader MockDbDataReader(List<TestData> ojectsToEmulate)
{
var moq = new Mock<DbDataReader>();
// This var stores current position in 'ojectsToEmulate' list
int count = -1;
moq.Setup(x => x.Read())
// Return 'True' while list still has an item
.Returns(() => count < ojectsToEmulate.Count - 1)
// Go to next position
.Callback(() => count++);
moq.Setup(x => x["BatchID"])
// Again, use lazy initialization via lambda expression
.Returns(() => ojectsToEmulate[count].ValidChar);
return moq.Object;
}

Resources