What to use as the key in a custom TempData provider? - asp.net-mvc

I'm investigating storing TempData in a better place. There is a walkthrough for how to do that with MongoDB but the key used for storage (item.SessionIdentifier == controllerContext.HttpContext.Request.UserHostAddress, the IP address) is clearly not working because multiple users/sessions can share the same public IP.
The consequence of using the IP as the key is that multiple users will see (and delete) each others data. In particular, during testing on your dev machine all sessions and browser instances will share the same temp data.
What would be a good key to use for TempData storage in some database?

Instead of assigning to tempdata directly call below method when ever assigning to object
public static string GetVisitorIPAddress(bool GetLan = false)
{
string visitorIPAddress = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (String.IsNullOrEmpty(visitorIPAddress))
visitorIPAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
if (string.IsNullOrEmpty(visitorIPAddress))
visitorIPAddress = HttpContext.Current.Request.UserHostAddress;
if (string.IsNullOrEmpty(visitorIPAddress) || visitorIPAddress.Trim() == "::1")
{
GetLan = true;
visitorIPAddress = string.Empty;
}
if (GetLan && string.IsNullOrEmpty(visitorIPAddress))
{
//This is for Local(LAN) Connected ID Address
string stringHostName = Dns.GetHostName();
//Get Ip Host Entry
IPHostEntry ipHostEntries = Dns.GetHostEntry(stringHostName);
//Get Ip Address From The Ip Host Entry Address List
IPAddress[] arrIpAddress = ipHostEntries.AddressList;
try
{
visitorIPAddress = arrIpAddress[arrIpAddress.Length - 2].ToString();
}
catch
{
try
{
visitorIPAddress = arrIpAddress[0].ToString();
}
catch
{
try
{
arrIpAddress = Dns.GetHostAddresses(stringHostName);
visitorIPAddress = arrIpAddress[0].ToString();
}
catch
{
visitorIPAddress = "127.0.0.1";
}
}
}
}
return visitorIPAddress.Split(',')[0].Trim();
}

Related

Large File upload to ASP.NET Core 3.0 Web API fails due to Request Body to Large

I have an ASP.NET Core 3.0 Web API endpoint that I have set up to allow me to post large audio files. I have followed the following directions from MS docs to set up the endpoint.
https://learn.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-3.0#kestrel-maximum-request-body-size
When an audio file is uploaded to the endpoint, it is streamed to an Azure Blob Storage container.
My code works as expected locally.
When I push it to my production server in Azure App Service on Linux, the code does not work and errors with
Unhandled exception in request pipeline: System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Request body too large.
Per advice from the above article, I have configured incrementally updated Kesterl with the following:
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel((ctx, options) =>
{
var config = ctx.Configuration;
options.Limits.MaxRequestBodySize = 6000000000;
options.Limits.MinRequestBodyDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
options.Limits.MinResponseDataRate =
new MinDataRate(bytesPerSecond: 100,
gracePeriod: TimeSpan.FromSeconds(10));
options.Limits.RequestHeadersTimeout =
TimeSpan.FromMinutes(2);
}).UseStartup<Startup>();
Also configured FormOptions to accept files up to 6000000000
services.Configure<FormOptions>(options =>
{
options.MultipartBodyLengthLimit = 6000000000;
});
And also set up the API controller with the following attributes, per advice from the article
[HttpPost("audio", Name="UploadAudio")]
[DisableFormValueModelBinding]
[GenerateAntiforgeryTokenCookie]
[RequestSizeLimit(6000000000)]
[RequestFormLimits(MultipartBodyLengthLimit = 6000000000)]
Finally, here is the action itself. This giant block of code is not indicative of how I want the code to be written but I have merged it into one method as part of the debugging exercise.
public async Task<IActionResult> Audio()
{
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
{
throw new ArgumentException("The media file could not be processed.");
}
string mediaId = string.Empty;
string instructorId = string.Empty;
try
{
// process file first
KeyValueAccumulator formAccumulator = new KeyValueAccumulator();
var streamedFileContent = new byte[0];
var boundary = MultipartRequestHelper.GetBoundary(
MediaTypeHeaderValue.Parse(Request.ContentType),
_defaultFormOptions.MultipartBoundaryLengthLimit
);
var reader = new MultipartReader(boundary, Request.Body);
var section = await reader.ReadNextSectionAsync();
while (section != null)
{
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(
section.ContentDisposition, out var contentDisposition);
if (hasContentDispositionHeader)
{
if (MultipartRequestHelper
.HasFileContentDisposition(contentDisposition))
{
streamedFileContent =
await FileHelpers.ProcessStreamedFile(section, contentDisposition,
_permittedExtensions, _fileSizeLimit);
}
else if (MultipartRequestHelper
.HasFormDataContentDisposition(contentDisposition))
{
var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name).Value;
var encoding = FileHelpers.GetEncoding(section);
if (encoding == null)
{
return BadRequest($"The request could not be processed: Bad Encoding");
}
using (var streamReader = new StreamReader(
section.Body,
encoding,
detectEncodingFromByteOrderMarks: true,
bufferSize: 1024,
leaveOpen: true))
{
// The value length limit is enforced by
// MultipartBodyLengthLimit
var value = await streamReader.ReadToEndAsync();
if (string.Equals(value, "undefined",
StringComparison.OrdinalIgnoreCase))
{
value = string.Empty;
}
formAccumulator.Append(key, value);
if (formAccumulator.ValueCount >
_defaultFormOptions.ValueCountLimit)
{
return BadRequest($"The request could not be processed: Key Count limit exceeded.");
}
}
}
}
// Drain any remaining section body that hasn't been consumed and
// read the headers for the next section.
section = await reader.ReadNextSectionAsync();
}
var form = formAccumulator;
var file = streamedFileContent;
var results = form.GetResults();
instructorId = results["instructorId"];
string title = results["title"];
string firstName = results["firstName"];
string lastName = results["lastName"];
string durationInMinutes = results["durationInMinutes"];
//mediaId = await AddInstructorAudioMedia(instructorId, firstName, lastName, title, Convert.ToInt32(duration), DateTime.UtcNow, DateTime.UtcNow, file);
string fileExtension = "m4a";
// Generate Container Name - InstructorSpecific
string containerName = $"{firstName[0].ToString().ToLower()}{lastName.ToLower()}-{instructorId}";
string contentType = "audio/mp4";
FileType fileType = FileType.audio;
string authorName = $"{firstName} {lastName}";
string authorShortName = $"{firstName[0]}{lastName}";
string description = $"{authorShortName} - {title}";
long duration = (Convert.ToInt32(durationInMinutes) * 60000);
// Generate new filename
string fileName = $"{firstName[0].ToString().ToLower()}{lastName.ToLower()}-{Guid.NewGuid()}";
DateTime recordingDate = DateTime.UtcNow;
DateTime uploadDate = DateTime.UtcNow;
long blobSize = long.MinValue;
try
{
// Update file properties in storage
Dictionary<string, string> fileProperties = new Dictionary<string, string>();
fileProperties.Add("ContentType", contentType);
// update file metadata in storage
Dictionary<string, string> metadata = new Dictionary<string, string>();
metadata.Add("author", authorShortName);
metadata.Add("tite", title);
metadata.Add("description", description);
metadata.Add("duration", duration.ToString());
metadata.Add("recordingDate", recordingDate.ToString());
metadata.Add("uploadDate", uploadDate.ToString());
var fileNameWExt = $"{fileName}.{fileExtension}";
var blobContainer = await _cloudStorageService.CreateBlob(containerName, fileNameWExt, "audio");
try
{
MemoryStream fileContent = new MemoryStream(streamedFileContent);
fileContent.Position = 0;
using (fileContent)
{
await blobContainer.UploadFromStreamAsync(fileContent);
}
}
catch (StorageException e)
{
if (e.RequestInformation.HttpStatusCode == 403)
{
return BadRequest(e.Message);
}
else
{
return BadRequest(e.Message);
}
}
try
{
foreach (var key in metadata.Keys.ToList())
{
blobContainer.Metadata.Add(key, metadata[key]);
}
await blobContainer.SetMetadataAsync();
}
catch (StorageException e)
{
return BadRequest(e.Message);
}
blobSize = await StorageUtils.GetBlobSize(blobContainer);
}
catch (StorageException e)
{
return BadRequest(e.Message);
}
Media media = Media.Create(string.Empty, instructorId, authorName, fileName, fileType, fileExtension, recordingDate, uploadDate, ContentDetails.Create(title, description, duration, blobSize, 0, new List<string>()), StateDetails.Create(StatusType.STAGED, DateTime.MinValue, DateTime.UtcNow, DateTime.MaxValue), Manifest.Create(new Dictionary<string, string>()));
// upload to MongoDB
if (media != null)
{
var mapper = new Mapper(_mapperConfiguration);
var dao = mapper.Map<ContentDAO>(media);
try
{
await _db.Content.InsertOneAsync(dao);
}
catch (Exception)
{
mediaId = string.Empty;
}
mediaId = dao.Id.ToString();
}
else
{
// metadata wasn't stored, remove blob
await _cloudStorageService.DeleteBlob(containerName, fileName, "audio");
return BadRequest($"An issue occurred during media upload: rolling back storage change");
}
if (string.IsNullOrEmpty(mediaId))
{
return BadRequest($"Could not add instructor media");
}
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
var result = new { MediaId = mediaId, InstructorId = instructorId };
return Ok(result);
}
I reiterate, this all works great locally. I do not run it in IISExpress, I run it as a console app.
I submit large audio files via my SPA app and Postman and it works perfectly.
I am deploying this code to an Azure App Service on Linux (as a Basic B1).
Since the code works in my local development environment, I am at a loss of what my next steps are. I have refactored this code a few times but I suspect that it's environment related.
I cannot find anywhere that mentions that the level of App Service Plan is the culprit so before I go out spending more money I wanted to see if anyone here had encountered this challenge and could provide advice.
UPDATE: I attempted upgrading to a Production App Service Plan to see if there was an undocumented gate for incoming traffic. Upgrading didn't work either.
Thanks in advance.
-A
Currently, as of 11/2019, there is a limitation with the Azure App Service for Linux. It's CORS functionality is enabled by default and cannot be disabled AND it has a file size limitation that doesn't appear to get overridden by any of the published Kestrel configurations. The solution is to move the Web API app to a Azure App Service for Windows and it works as expected.
I am sure there is some way to get around it if you know the magic combination of configurations, server settings, and CLI commands but I need to move on with development.

Cloudflare service worker code to "Bypass cache on cookie" not working

I wrote this code as a Cloudflare Service Worker which is meant to precisely emulate their native function for "Bypass cache on cookie". Specifically, if someone has a Wordpress cookie - it would bypass cache, otherwise it does not.
It does not seem to function at all - in that despite having a cookie and being logged in (confirmed via Chrome developer tools) - I still get a Cloudflare cache HIT on this example domain - Tallyfy. Anything wrong with it? Help appreciated!
// A Service Worker which skips cache if the request contains a cookie.
addEventListener('fetch', event => {
let request = event.request;
var flag=false;
if(request.headers.cookie) {
var pairs = request.headers.cookie.split(";");
var patt = new RegExp("wp-.*|wordpress.*|comment_.*|woocommerce_.*")
for(var i=0;i<pairs.length;i++){
if(patt.test(pairs[i])){
flag = true;
break;
}
}
}
if (request.headers.has('Cookie') && flag) {
// Cookie present. Add Cache-Control: no-cache.
let newHeaders = new Headers(request.headers)
newHeaders.set('Cache-Control', 'no-cache')
event.respondWith(fetch(request, {headers: newHeaders}))
}
// Use default behavior.
return
})
try this and let me know
addEventListener('fetch', event => {
let request = event.request
var flag = false;
if (request.headers.has('Cookie')) {
var cookie = request.headers.get('Cookie');
pairs = cookie.split(";");
var patt = new RegExp("wordpress_logged_in.*|wp_woocommerce_session.*");
for(var i=0;i<pairs.length;i++){
if(patt.test(pairs[i])){
flag = true;
break;
}
}
console.log(flag);
if (request.headers.has('Cookie') && flag) {
let newHeaders = new Headers(request.headers)
newHeaders.set('Cache-Control', 'no-cache')
newHeaders.set('Pragma', 'no-cache')
event.respondWith(fetch(request, {headers: newHeaders}))
}
// Use default behavior.
return;
}
})

EF4 update navigation property An entity object cannot be referenced by multiple instances of IEntityChangeTracker

I am trying to implement a let's say "change my account email address" fonctionality.
I want to keep backup of all user emails in (R_EmailAddressHistory table).
Here are some of my project's code.
public bool ChangeEmailAddress(string username, string newEmailAddress, string callbackUrl)
{
DateTime currentUtcTime = DateTime.UtcNow;
R_User currentUser = UserRepo.GetSingle(whereCondition: w=>w.Username == username);
currentUser.UpdateDate = currentUtcTime;
if (currentUser.HasPendingNewEmail)
{
R_EmailAddressHistory currentPendingRequest = EmailHistoRepo.GetSingle(whereCondition: w => w.StatusID == (int)Reno.Common.Enums.RecordStatus.Pending && w.R_User.GId == currentUser.GId);
currentPendingRequest.NewEmail = newEmailAddress;
currentPendingRequest.UpdateDate = currentUtcTime;
EmailHistoRepo.Update(currentPendingRequest);
}
else
{
currentUser.HasPendingNewEmail = true;
R_EmailAddressHistory newEmail = new R_EmailAddressHistory();
newEmail.UserId = currentUser.GId;
newEmail.R_User = currentUser;
newEmail.NewEmail = newEmailAddress;
newEmail.InsertDate = currentUtcTime;
newEmail.StatusID = (int) Reno.Common.Enums.RecordStatus.Pending;
currentUser.R_EmailAddressHistory.Add(newEmail);
}
IdentityResult idtResult = UserRepo.Update(currentUser);
if(idtResult == IdentityResult.Succeeded)
{
//Send notification to current email address for validation before proceeding change email process
bool sendResult = Communication.EmailService.SendChangeEmailValidation(username,currentUser.Email, newEmailAddress, callbackUrl);
return sendResult;
}
else
{
return false;
}
}
The previous method is use to change an email address. Each of my tables (R_User and EmailAddressHistory ) has Repository (UserRepo and EmailHistoRepo). The implement the same IRepositoryBase class, here is the Update methode
public IdentityResult Update(T entity)
{
try
{
if (_currentContext.DbContext.Entry(entity).State == EntityState.Detached)
{
_currentContext.DbContext.Set<T>().Attach(entity);
}
_currentContext.DbContext.Entry(entity).State = EntityState.Modified;
return IdentityResult.Succeeded;
}
catch
{
return IdentityResult.Failed;
}
}
When a user has already a non validate new email address, when he request to change his current email address, I show him the pending new email address and he can change it, in this case I whant to update my historical table instead of creating a new one, cause only one pending new email address is allow. In such a case, my code failed in the line EmailHistoRepo.Update(currentPendingRequest) throwing the error : An entity object cannot be referenced by multiple instances of IEntityChangeTracker.
Can anyone help me?
Thanks
EDIT
I am using MVC(4) with a unitOfWork. My UOW is initialized in a the Controller the first time the DB is queried and the Commit is done in the global.asax file in Appalication_EndRequest (see below).
protected void Application_EndRequest(Object sender, EventArgs e)
{
CommitChanges();
}
private void CommitChanges()
{
Reno.BLL.Services.Singleton.UnitOfWork unitOfWork = Reno.BLL.Services.Singleton.UnitOfWork.GetCurrentInstance(false);
if (unitOfWork != null)
{
unitOfWork.Commit();
unitOfWork.Dispose();
}
}
Your currentUser is modified before updating the emailaddress. Save the changes to currentUser first.
Something like this:
R_User currentUser = UserRepo.GetSingle(whereCondition: w=>w.Username == username);
currentUser.UpdateDate = currentUtcTime;
bool pendingNewEmail = currentUser.HasPendingNewEmail;
UserRepo.Update(currentUser);
if (pendingNewEmail)
{
R_EmailAddressHistory currentPendingRequest = EmailHistoRepo.GetSingle(whereCondition: w => w.StatusID == (int)Reno.Common.Enums.RecordStatus.Pending && w.R_User.GId == currentUser.GId);
currentPendingRequest.NewEmail = newEmailAddress;
currentPendingRequest.UpdateDate = currentUtcTime;
EmailHistoRepo.Update(currentPendingRequest);
}
else
I finally found the answer. The problem was that when I first get the user in line
R_User currentUser = UserRepo.GetSingle(whereCondition: w=>w.Username == username);
The currentUser variable hold a refrence of all of its R_EmailAddressHistory.
And then after, I queried the DB (2nd time) to get the pending email change request (or type R_EmailAddressHistory) to modify its new email and its update date, in line
R_EmailAddressHistory currentPendingRequest = EmailHistoRepo.GetSingle(whereCondition: w => w.StatusID == (int)Reno.Common.Enums.RecordStatus.Pending && w.R_User.GId == currentUser.GId);
currentPendingRequest.NewEmail = newEmailAddress;
currentPendingRequest.UpdateDate = currentUtcTime;
But te last code updates only currentPendingRequest while another reference of the same object which is in currentUser.R_EmailAddressHistory is not update and was already tracked by the context. Therefore, by doing an update on the new instance (EmailHistoRepo.Update(currentPendingRequest)), the code failed: the same object if referenced in 2 places.
So, the solution was (the only thing I modified):
R_User currentUser = UserRepo.GetSingle(whereCondition: w=>w.Username == username);
currentUser.UpdateDate = currentUtcTime;
if (currentUser.HasPendingNewEmail)
{
R_EmailAddressHistory currentPendingRequest = currentUser.R_EmailAddressHistory.Where(h => h.StatusID == (int)Reno.Common.Enums.RecordStatus.Pending).First(); // EmailHistoRepo.GetSingle(whereCondition: w => w.StatusID == (int)Reno.Common.Enums.RecordStatus.Pending && w.R_User.GId == currentUser.GId);
currentPendingRequest.NewEmail = newEmailAddress;
currentPendingRequest.UpdateDate = currentUtcTime;
}
I decided to modify the instance in currentUser variable.

Check wifi condition in Blackberry application

I have developed an application for blackberry devices. The application is working fine if it uses internet via data service provider.
I have BB 9550 and I want to use my application using wifi. I tried a lot but I cant get proper answer to check wifi condition.
How we can differentiate to run our application for wifi or data service provider?
For checking wifi is connected or not the following method will help you.
public static boolean isWifiConnected()
{
try
{
if (RadioInfo.getSignalLevel(RadioInfo.WAF_WLAN) != RadioInfo.LEVEL_NO_COVERAGE)
{
return true;
}
}
catch(Exception e)
{
System.out.println("Exception during get WiFi status");
}
return false;
}
if wifi is not connected the following methods will help to add data service.
public static String getConnParam(){
String connectionParameters = "";
if (WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED) {
// Connected to a WiFi access point
connectionParameters = ";interface=wifi";
} else {
int coverageStatus = CoverageInfo.getCoverageStatus();
ServiceRecord record = getWAP2ServiceRecord();
if (record != null
&& (coverageStatus & CoverageInfo.COVERAGE_DIRECT) ==
CoverageInfo.COVERAGE_DIRECT) {
// Have network coverage and a WAP 2.0 service book record
connectionParameters = ";deviceside=true;ConnectionUID="
+ record.getUid();
} else if ((coverageStatus & CoverageInfo.COVERAGE_MDS) ==
CoverageInfo.COVERAGE_MDS) {
// Have an MDS service book and network coverage
connectionParameters = ";deviceside=false";
} else if ((coverageStatus & CoverageInfo.COVERAGE_DIRECT) ==
CoverageInfo.COVERAGE_DIRECT) {
// Have network coverage but no WAP 2.0 service book record
connectionParameters = ";deviceside=true";
}
}
return connectionParameters;
}
private static ServiceRecord getWAP2ServiceRecord() {
ServiceBook sb = ServiceBook.getSB();
ServiceRecord[] records = sb.getRecords();
for(int i = 0; i < records.length; i++) {
String cid = records[i].getCid().toLowerCase();
String uid = records[i].getUid().toLowerCase();
if (cid.indexOf("wptcp") != -1 &&
uid.indexOf("wifi") == -1 &&
uid.indexOf("mms") == -1) {
return records[i];
}
}
return null;
}
Example to use above methods.
String connParams=(isWifiConnected())?";interface=wifi":getConnParam();
Hope This will help you
try this:
private static String getParameters() {
if (GetWiFiCoverageStatus()) {
return ";deviceside=true;interface=wifi";
}
else {
return yourParametersForEdge
}
}
private static boolean GetWiFiCoverageStatus() {
if((WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED)) {
return true;
}
else
return false;
}
And when you need to connect, you'll have to add the parameters to the URL:
yourUrl = yourUrl + getParameters();

Grails Issue Dealing With Tcp Client & Tcp Server

I created a Tcp Client & Tcp Server in Groovy awhile back and had no issues with it. I was only connecting to one machine at the time to gather data. This time I am attempting to connect to the script on multiple hosts and it is only saving one of the hosts information in my grails app.
My Grails application is simple, it has a domain class for Machines (basically the computers and the information on them that I seek) and it will use my TcpClient.groovy script to connect and gather information from the TcpServer.groovy on the other computers. For each host, it should save the information gathered, however, it seems to skip right over saving any host aside from the last one.
Tcp Client :
//TCP CLIENT
public void queryData(def hosts) {
for(int aHost = 0; aHost < hosts.size; aHost++) {
cristalClient(hosts[aHost]);
}
}
public void cristalClient(String host) {
commands = ["dateScan", "computerName", "ip", "quit"]
answers = [commands.size]
requestSocket = new Socket(host, 2000)
r = new BufferedReader(new InputStreamReader(requestSocket.getInputStream()));
w = new BufferedWriter(new OutputStreamWriter(requestSocket.getOutputStream()));
String message = "Connection was successful"
message = readAvailable(r)
println("Sever>" + message)
for(int n = 0; n < commands.size; n++) {
sendMessage(commands[n]);
answers[n] = readAvailable(r)
}
lastRead = answers[0]
machineName = answers[1]
ipAddress = answers[3]
w.flush()
w.close()
}
public String readAvailable(r) {
String out = ""
String dum = null
while((dum = r.readLine()) !=null) {
if(dum == ">>EOF<<") return out
if(out.length() > 0) out += "\r\n"
out += dum
}
return out
}
public void sendMessage(msg) {
w.write(msg+"\r\n");
w.flush();
println("Client>" + msg);
}
public void printData(abc) {
abc.eachWithIndex { it, index ->
println "Drive $index"
it.each { k, v ->
println "\t$k = $v"
}
}
}
Tcp Server :
//TCP Server
def server = new ServerSocket(2000)
println("Waiting for connection")
server.accept() { socket ->
socket.withStreams { input, output ->
w = new BufferedWriter(new OutputStreamWriter(output))
String message = "Connection was successful"
r = new BufferedReader(new InputStreamReader(input))
while(true) {
if(message != null) {
sendMessage(message)
message = null
}
String a = r.readLine()
if(a == "dateScan") {
message = new Date
} else if(a == "computerName") {
message = InetAddress.getLocalHost().hostName
} else if(a == "ip") {
message = InetAddress.getLocalHost().getHostAddress()
} else if(a == "quit") {
server.close()
return
} else {
message = "$a command unknown."
println message
}
}
}
}
def sendMessage(String msg) {
println( "sending: >" + msg + "<" )
w.writeLine(msg)
w.writeLine(">>EOF<<")
w.flush();
}
Grails Controller :
//Grails Controller
CollectMachines {
def w = new tcpClient()
def hosts = ["winXp", "Win7"]
w.queryData(hosts)
def abc = w.hardDrive
abc.each { println it }
int numberOfDrives = abc.size()
//add new machine
numberOfDrives.times {
def machineName = abc.computerName[it]
def machineInstance = Machine.findByMachineName(machineName)
if (!machineInstance) {
machineInstance = new Machine(machineName)
}
def lastScan = abc.lastScan[it]
def scanDate = new Date().parse("E MMM dd H:m:s z yyyy", lastScan)
def ipAddress = abc.ipAddress[it]
machineInstance.setIpAddress(ipAddress)
machineInstance.setDateScanned(scanDate)
machineInstance.save()
}
redirect(action: "list")
}
Do I need to put a pause in so that the server has time to send a response? My Tcp Client does send out all the commands but only gets responses for the last set of commands.
Also, sorry for the indentation issues with my code snippets, I'm not sure why they are messed up.
.
There are a few problems with your code. tcpClient never assigns to hardDrive, for example. Assuming this is an oversight, I think the real problem is that tcpClient is querying data for multiple hosts, and storing all the results in the same instance variables answers, and ultimately lastRead, machineName, and ipAddress.
You need to store the results for each host separately. One way would be to have answers be a map of lists. For example, answers[host][0] would be the first answer for a given host.
I don't think any kind of pause is necessary.

Resources